簡體   English   中英

變量處理的bash引號在擴展為命令時處理不同

[英]bash quotes in variable treated different when expanded to command

通過例子解釋問題......

證明 - 變量擴展后,--chapters之后的單引號會被轉義(我沒想到):

prompt@ubuntu:/my/scripts$ cat test1.sh
#!/bin/bash
actions="--tags all:"
actions+=" --chapters ''"
mkvpropedit "$1" $actions

prompt@ubuntu:/my/scripts$ ./test1.sh some.mkv
Error: Could not open '''' for reading.

現在由於某種原因,mkvpropedit接收雙引號作為文件名的一部分(我也沒想到):

prompt@ubuntu:/my/scripts$ cat test1x.sh
#!/bin/bash
command="mkvpropedit \"$1\""
command+=" --tags all:"
command+=" --chapters ''"
echo "$command"
$command

prompt@ubuntu:/my/scripts$ ./test1x.sh some.mkv
mkvpropedit "some.mkv" --tags all: --chapters ''
Error: Could not open '''' for reading.

上面的echo'd命令似乎是正確的。 將相同的文本放在另一個腳本中會得到預期的結果:

prompt@ubuntu:/my/scripts$ cat test2.sh
#!/bin/bash
mkvpropedit "$1" --tags all: --chapters ''

prompt@ubuntu:/my/scripts$ ./test2.sh some.mkv
The file is being analyzed.
The changes are written to the file.
Done.

任何人都可以解釋為什么報價不符合預期。 我發現在這個問題上搜索很困難,因為網上有很多其他的引用討論。 我甚至不知道如何在沒有例子的情況下解釋這個問題。

我擔心有一天,參數中的文件名包含一些破壞一切的字符,因此可能過多引用。 我不明白為什么直接在腳本中輸入或通過變量提供時相同的命令執行方式不同。 請賜教。

謝謝閱讀。

需要記住的重要一點是,在最初解析命令行時, 引號只會被刪除一次 由於參數替換( $foo )或命令替換( $(cmd args) )而插入命令行的引用不被視為特殊字符。 [注1]

這似乎與空格和glob元字符不同。 在參數/命令替換之后發生字拆分和路徑名擴展(除非替換發生在引號內)。 [筆記2]

結果是,創建一個bash變量$args幾乎是不可能的

cmd $args

如果$args包含引號,則不會刪除它們。 $args中的單詞由空格序列分隔,而不是單個空白字符。

唯一的方法是將$IFS設置$IFS包含一些非空白字符; 然后,該字符可以在$args作為單字符分隔符使用。 但是, 沒有辦法在值中引用字符 ,因此一旦這樣做,您選擇的字符除了作為分隔符之外不能使用。 這通常不太令人滿意。

但是有一個解決方案:bash數組。

如果將$args轉換為數組變量,則可以使用重復引用語法對其進行擴展:

cmd "${args[@]}"

它為$args每個元素生成一個單詞,並禁止在這些單詞上進行單詞拆分和路徑名擴展,因此它們最終成為文字。

所以,例如:

actions=(--tags all:)
actions+=(--chapters '')
mkvpropedit "$1" "${actions[@]}"

可能會做你想要的。 那會:

args=("$1")
args+=(--tags)
args+=(all:)
args+=(--chapters)
args+=('')
mkvpropedit "${args[@]}"

等等

command=(mkvpropedit "$1" --tags all: --chapters '')
"${command[@]}"

我希望這是半透明的。

man bash (或在線版本 )包含一個關於bash匯編命令的詳細說明,從“EXPANSION”部分開始。 值得閱讀以獲得完整的解釋。


筆記:

  1. 這不適用於evalbash -c類的命令,它們在命令行處理后再次評估它們的參數。 但那是因為命令行處理發生了兩次。

  2. 單詞拆分與“將命令划分為單詞”不同,這在解析命令時會發生。 首先,單詞拆分使用$IFS的值作為分隔符,而命令行解析使用空格。 但這些都不是在引號內完成的,所以它們在這方面是相似的。 在任何情況下,在參數替換之前和之后,單詞都以這種或那種方式分開。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM