我花了大約一個小時嘗試編寫一個非常簡單的 bash 腳本,但我從未感到如此愚蠢。
所以我有一個可能包含星號的字串列表(如果重要的話,它們是套件管理器的套件選擇器規範)。我需要建立一個保留這些星號的命令行,然後呼叫一個程式。這是我天真的嘗試:
xs="foo/bar */*"
xs_cmd=""
for x in $xs; do
xs_cmd="$xs_cmd -0 $x "
done
echo $xs_cmd
我需要的echo
呼叫相當於
echo -0 foo/bar -0 '*/*'
其輸出-0 foo/bar -0 */*
.
PS 實際上,第一行稍微複雜一些: xs="$some foo/bar */* $(get_others)"
。
如果您在包含 的目錄中執行此腳本a/b
,您將得到-0 foo/bar -0 a/b
。
當我將最後一行更改為
echo "$xs_cmd" # note the quotes
我明白了-0 foo/bar -0 a/b
,首先這不是我想要的,因為現在我正在echo
調用單身的論證,此外,這告訴我擴展發生得更早,可能是在for
循環中。
但我無法更改線路,for
因為
for x in "$xs"; do # note the quotes
只會使循環迭代一次:(-0 foo/bar */*
有一個-0
)所以添加這些引號並不是一個肯定的選擇。
現在,如果我恢復到原始腳本並將第一行替換為
xs="foo/bar '*/*'" # note additional single quotes
我明白-0 foo/bar -0 '*/*'
(單引號不應該在那裡)。
看來我嘗試了引號和星號反斜線轉義的每種組合,但我實際上不知道現在該怎麼做。
答案1
我使用了您的原始腳本,但在第一行(僅)使用單引號,並且它按照我認為您想要的方式工作(-0
在每個文件路徑之前):-
xs='foo/bar */*'
xs_cmd=""
for x in $xs; do
xs_cmd="$xs_cmd -0 $x "
done
echo $xs_cmd
如果任何檔案路徑中嵌入了空格,您在使用它時可能會發現問題。如果是這樣,請將循環中的命令更改為:-
xs_cmd="$xs_cmd -0 \"$x\" "
答案2
根據您想要實現的目標,您需要引用這些*/*
:
xs="foo/bar '*/*'" #!
xs_cmd=""
for x in $xs ; do
xs_cmd="$xs_cmd -0 $x "
done
echo $xs_cmd
eval echo $xs_cmd
eval "echo $xs_cmd"
或使用數組,或兩者兼具:
xs=("foo/bar" "*/*") #!
xs_cmd=""
for x in "${xs[@]}"; do
xs_cmd="$xs_cmd -0 '$x' " #!
done
echo "$xs_cmd"
eval "echo $xs_cmd"