2016-09-20 134 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 ......