2016-09-20 102 views
0

说空间我有一个变量$ARGS其中包含以下内容:BASH外壳扩展参数与可变

file1.txt "second file.txt" file3.txt 

如何传递的$ARGS内容作为参数传递给一个命令(比如cat $ARGS,例如)将"second file.txt"作为一个参数处理,而不是将其分解为"secondfile.txt"

理想情况下,我希望能够将参数传递给任何命令,就像它们存储在变量中一样(从文本文件中读取,但我认为这没有关系)。

谢谢!

+6

不要使用变量;使用一个数组:“ARGS =(”file1.txt“”second file.txt“”file3.txt“)'然后传递它:'”$ {ARGS [@]}“'。 –

+0

如果设置是在一个文本文件中,并且参数之间的分隔符是空格,我不明白为什么你认为你所看到的行为不正确。我的意思是我可以看到你想要做什么,但是然后从文本文件中读取空格分隔的参数可能是错误的解决方案。如果您的需求很复杂,也许可以使用某种结构化的文件格式。 – tripleee

回答

2

这是可能做到这一点既没有庆典阵列或eval:这是一xargs没有-0-d扩展(主要是创建错误的行为)的行为的几个地方实际上是有用的。

# this will print each argument on a different line 
# ...note that it breaks with arguments containing literal newlines! 
xargs printf '%s\n' <<<"$ARGS" 

......或者......

# this will emit arguments in a NUL-delimited stream 
xargs printf '%s\0' <<<"$ARGS" 

# in bash 4.4, you can read this into an array like so: 
readarray -t -d '' args < <(printf '%s\0' "$ARGS") 
yourprog "${args[@]}" # actually run your programs 

# in bash 3.x or newer, it's just a bit longer: 
args=(); 
while IFS= read -r -d '' arg; do 
    args+=("$args") 
done < <(xargs printf '%s\0' <<<"$ARGS") 
yourprog "${args[@]}" # actually run your program 

# in POSIX sh, you can't safely handle arguments with literal newlines 
# ...but, barring that, can do it like this: 
set -- 
while IFS= read -r arg; do 
    set -- "[email protected]" "$arg" 
done < <(printf '%s\n' "$ARGS" | xargs printf '%s\n') 
yourprog "[email protected]" # actually run your program 

...或者,让xargs本身做的调用:

# this will call yourprog with ARGS given 
# ...but -- beware! -- will cause bugs if there are more arguments than will fit on one 
# ...command line invocation. 
printf '%s\n' "$ARGS" | xargs yourprog 
1

正如Jonathan Leffler所提到的,你可以用数组来完成。

my_array=("file1.txt" "second file.txt" "file3.txt") 
cat "${my_array[1]}" 

数组的索引从0开始。所以,如果你想你的cat数组中的第一个文件,你会使用索引号0 "${my_array[0]}"。如果您想对所有元素运行命令,请用@*替换索引号。例如,您可以使用"${my_arryay[0]}"来代替"${my_array[@]}"请确保您引用该数组,否则它将使用空格将任何文件名视为单独的文件。

或者,如果由于某种原因引用数组存在问题,则可以将IFS(表示内部字段分隔符)设置为等于换行符。如果您这样做,最好在将默认IFS更改为变量之前将其保存为变量,以便您可以将其重新设置为脚本完成后的方式。例如:

# save IFS to a variable  
old_IFS=${IFS-$' \t\n'} 
#set IFS to a newline 
IFS='$\n' 

# run your script 
my_array=("file1.txt" "second file.txt" "file3.txt") 
cat ${my_array[1]} 

# restore IFS to its default state 
IFS=$old_IFS 

除非必须,否则最好不要乱用IFS。如果你可以引用数组来使你的脚本工作,那么你应该这样做。

对于深入了解一个更成使用数组看到:

+0

请考虑使用ABS以外的来源 - 它[相当臭名昭着](http://wooledge.org/~greybot/meta/abs)在其示例中使用了不良做法。有[数组上的bash-hacker页面](http://wiki.bash-hackers.org/syntax/arrays),[数组上的BashGuide](http://mywiki.wooledge.org/BashGuide/Arrays),和[BashFAQ#5](http://mywiki.wooledge.org/BashFAQ/005)。 –

+0

另外,如果您的原始IFS值未设置,那么您在此处执行的'old_IFS' shuffle将不会按您的意愿操作。考虑'old_IFS = $ {IFS- $'\ t \ n'}',如果原始值未设置(与set-to-an-empty-string相反),则将默认值存储在'old_IFS'中。 –

+0

感谢您的信息。我已经更新了答案。 –

0

没有bash主义,普通的shell代码可能需要一个eval

# make three temp files and list them. 
cd /tmp ; echo ho > ho ; echo ho ho > "ho ho" ; echo ha > ha ; 
A='ho "ho ho" ha' ; eval grep -n '.' $A 

输出:

ho:1:ho 
ho ho:1:ho ho 
ha:1:ha 

注意eval是强大的,if not used responsibly can lead to mischief ......