我目前正在使用供应商提供的软件,该软件试图将附件文件发送到另一个脚本,该脚本将从列出的文件中进行文本提取。当我们从包含空格的外部源接收文件时脚本失败,因为供应商提供的软件没有用引号括起文件名 - 这意味着当运行文本提取脚本时,它会收到一个文件名,该文件将在空格上分开并在提取器脚本上导致错误。供应商提供的软件不可由我们编辑。
整个过程设计为自动转换,因此使用这种可能随机丢入齿轮的扳手是一个问题。
我们要做的是在文本提取器脚本中处理间隔名称,因为这是我们可以控制的部分。快速谷歌之后,似乎更改脚本的IFS值将是快速解决方案,但不幸的是,该脚本将在扩展已经残缺传入数据后生效。
我正在使用的脚本包含-e值,-i值和-o值。这些值是从供应商提供的脚本发送的,我没有编辑控制权。
#!/bin/bash
usage() { echo "Usage: $0 -i input -o output -e encoding" 1>&2; exit 1; }
while getopts ":o:i:e:" o; do
case "${o}" in
i)
inputfile=${OPTARG}
;;
o)
outputfile=${OPTARG}
;;
e)
encoding=${OPTARG}
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
...
...
<Uses the inputfile, outputfile, and encoding variables>
我承认,可能有些内容我不完全理解,它可能是一个简单的修复,但我的最终目标是能够提取所有包含1的-o,-i和-e值,不管每个部分内的空格。我可以在提取文件名值
后处理引用脚本答案 0 :(得分:3)
您发布的脚本片段与参数中的空格没有任何问题。
例如,以下内容不需要引用(因为它是一项任务):
inputfile=${OPTARG}
脚本中$inputfile
的所有其他用法都应加双引号。
重要的是如何调用此脚本。
这会失败,只会将hello
分配给变量inputfile
:
$ ./script.sh -i hello world.txt
字符串world.txt
将提示getopts
函数停止处理命令行,脚本将继续shift
(world.txt
将保留在{{1}之后)。
以下内容会将字符串$1
正确分配给hello world.txt
:
inputfile
就像
一样$ ./script.sh -i "hello world.txt"
答案 1 :(得分:1)
以下脚本使用awk拆分参数,同时在文件名中包含空格。参数可以是任何顺序。它不处理参数中的多个连续空格,它将它们折叠为一个。
#!/bin/bash
IFS=' '
str=$(printf "%s" "$*")
istr=$(echo "${str}" | awk 'BEGIN {FS="-i"} {print $2}' | awk 'BEGIN {FS="-o"} {print $1}' | awk 'BEGIN {FS="-e"} {print $1}')
estr=$(echo "${str}" | awk 'BEGIN {FS="-e"} {print $2}' | awk 'BEGIN {FS="-o"} {print $1}' | awk 'BEGIN {FS="-i"} {print $1}')
ostr=$(echo "${str}" | awk 'BEGIN {FS="-o"} {print $2}' | awk 'BEGIN {FS="-e"} {print $1}' | awk 'BEGIN {FS="-i"} {print $1}')
inputfile=""${istr}""
outputfile=""${ostr}""
encoding=""${estr}""
# call the jar
调用jar时出现问题,其中Java在带有空格的文件名上抛出MalformedUrlException。
答案 2 :(得分:1)
因此,在阅读评论后,我们认为尽管对于每个场景可能都不是正确答案,但这个特定场景的正确答案是手动提取部分。
因为我们正在为传递给它的预构建脚本构建它,并且我们不会很快更新该脚本,所以我们可以肯定地接受这个脚本将始终接收-i,-o和 - e标志,它们之间会有空格,这会导致传入的所有部分存储在$*
的不同变量中。
我们可以假设标志后面的文本是对标志的响应,直到引用另一个标志。这留下了3个场景:
我一直遇到的其他问题之一就是尝试将字符串文字等同于我的IF语句中的变量。为了解决这个问题,我在数组变量中预先存储了所有相关数据,因此我可以测试$ variable == $ otherVariable。
虽然我不希望它改变,但如果三个标志的出现顺序与我们预期的不同,我们也会处理该怎么做(我们的假设是它们列为i,o,e ......但我们可以不要惊讶地看到通过的是什么。参数按读入顺序转储到数组中,并行数组跟踪插槽0,1,2中的项是否与i,o,e相关。
最终结果仍有一个缺陷:如果文件名中有多个连续的空格,则在处理之前修剪空白,我只能占一个空格。但是当我们在遇到一个带有空格的文件之前处理超过4000个文件时,我发现不太可能使用命名约定我们会遇到多个空格。
此时,无论如何我们都必须踩到一个罕见的干预。
最终的代码更改如下:
#!/bin/bash
IFS='|'
position=-1
ioeArray=("" "" "")
previous=""
flagArr=("-i" "-o" "-e" " ")
ioePattern=(0 1 2)
#echo "for loop:"
for i in $*; do
#printf "%s\n" "$i"
if [ "$i" == "${flagArr[0]}" ] || [ "$i" == "${flagArr[1]}" ] || [ "$i" == "${flagArr[2]}" ]; then
((position += 1));
previous=$i;
case "$i" in
"${flagArr[0]}")
ioePattern[$position]=0
;;
"${flagArr[1]}")
ioePattern[$position]=1
;;
"${flagArr[2]}")
ioePattern[$position]=2
;;
esac
continue;
fi
if [[ $previous == "-"* ]]; then
ioeArray[$position]=${ioeArray[$position]}$i;
else
ioeArray[$position]=${ioeArray[$position]}" "$i;
fi
previous=$i;
done
echo "extracting (${ioeArray[${ioePattern[0]}]}) to (${ioeArray[${ioePattern[1]}]}) with (${ioeArray[${ioePattern[2]}]}) encoding."
inputfile=""${ioeArray[${ioePattern[0]}]}"";
outputfile=""${ioeArray[${ioePattern[1]}]}"";
encoding=""${ioeArray[${ioePattern[2]}]}"";