說空間我有一個變量$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