说空间我有一个变量$ARGS
其中包含以下内容:BASH外壳扩展参数与可变
file1.txt "second file.txt" file3.txt
如何传递的$ARGS
内容作为参数传递给一个命令(比如cat $ARGS
,例如)将"second file.txt"
作为一个参数处理,而不是将其分解为"second
和file.txt"
?
理想情况下,我希望能够将参数传递给任何命令,就像它们存储在变量中一样(从文本文件中读取,但我认为这没有关系)。
谢谢!
说空间我有一个变量$ARGS
其中包含以下内容:BASH外壳扩展参数与可变
file1.txt "second file.txt" file3.txt
如何传递的$ARGS
内容作为参数传递给一个命令(比如cat $ARGS
,例如)将"second file.txt"
作为一个参数处理,而不是将其分解为"second
和file.txt"
?
理想情况下,我希望能够将参数传递给任何命令,就像它们存储在变量中一样(从文本文件中读取,但我认为这没有关系)。
谢谢!
这是可能做到这一点既没有庆典阵列或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
正如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。如果你可以引用数组来使你的脚本工作,那么你应该这样做。
对于深入了解一个更成使用数组看到:
请考虑使用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)。 –
另外,如果您的原始IFS值未设置,那么您在此处执行的'old_IFS' shuffle将不会按您的意愿操作。考虑'old_IFS = $ {IFS- $'\ t \ n'}',如果原始值未设置(与set-to-an-empty-string相反),则将默认值存储在'old_IFS'中。 –
感谢您的信息。我已经更新了答案。 –
没有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 ......
不要使用变量;使用一个数组:“ARGS =(”file1.txt“”second file.txt“”file3.txt“)'然后传递它:'”$ {ARGS [@]}“'。 –
如果设置是在一个文本文件中,并且参数之间的分隔符是空格,我不明白为什么你认为你所看到的行为不正确。我的意思是我可以看到你想要做什么,但是然后从文本文件中读取空格分隔的参数可能是错误的解决方案。如果您的需求很复杂,也许可以使用某种结构化的文件格式。 – tripleee