[英]Escaping question mark character in sed bash script variable
我有一組保存的html文件,它們中的鏈接的格式為http://mywebsite.com/showfile.cgi?key=somenumber,但我想取消問號(故事是Firefox討厭?並隨機轉換它到%3F,我確定有一些魔術修復方法,但這是另一個問題……)
但是,我認為當bash將選項存儲為變量時,我的代碼導致問號字符無法正確讀取/保存/處理
# Doesn't work (no pattern matched)
SED_OPTIONS='-i s/\.cgi\?key/\.cgikey/g'
# Works e.g. http://mywebsite.com/showfileblah?key=somenumber
SED_OPTIONS='-i s/\.cgi/blah/g'
# Leaves question mark in e.g. http://mywebsite.com/showfile.blah?key=somenumber
SED_OPTIONS='-i s/cgi\?/blah/g'
# Actual sed command run when using SED_OPTIONS (I define FILES earlier in
# the code)
sed $SED_OPTIONS $FILES
# Not using the SED_OPTIONS variable works
# e.g. http://mywebsite.com/showfile.cgikey=somenumber
sed -i s/\.cgi\?key/\.cgikey/g $FILES
如何使用SED_OPTIONS變量使完整命令起作用?
在變量中存儲選項和參數列表的最安全方法是使用數組 :
也:
-r
或-E
選項),所以?
不是特殊字符。 並且不需要逃避。 .
。 g
,因為您只需要替換每行1次即可。 # Create array with individual options/arguments.
SED_ARGS=( '-i' 's/\.cgi?key/.cgikey/' )
# Invoke `sed` with array - note the double-quoting.
sed "${SED_ARGS[@]}" $FILES
同樣,將數組用於輸入文件列表會更安全。 僅當單個文件名不包含嵌入式空格或其他受Shell擴展限制的元素時, $FILES
才起作用。
通常:
sed
腳本-防止shell解釋它們。 我建議將sed
的參數存儲在數組中:
SED_OPTIONS=( '-i' '-e' 's/\.cgi?key/\.cgikey/g' )
sed "${SED_OPTIONS[@]}" $FILES
但是,那只是麻煩的一部分。
首先,請注意當您鍵入:
sed -i s/\.cgi\?key/\.cgikey/g $FILES
sed
看到的script參數實際上是:
s/.cgi?key/.cgikey/g
因為您沒有使用任何引號來保留反斜杠。 (為演示printf "%s\\n" s/\\.cgi\\?key/\\.cgikey/g
,請使用printf "%s\\n" s/\\.cgi\\?key/\\.cgikey/g
,從而避免出現任何有關echo
是否正在解釋反斜杠的問題。)這樣做的副作用是URL這樣如:
http://example.com/nodotcgi?key=value
將映射到:
http://example.com/nodo.cgikey=value
設置SED_OPTIONS時使用單引號可確保在需要的地方保留反斜杠,並且不要在?
之前放置反斜杠?
作品。 我的Mac上同時有GNU sed
和BSD sed
。 為了清楚起見,我將它們別名為gnu-sed
和bsd-sed
。 請注意,BSD sed
需要-i
的后綴,並且不接受-i
標准輸入。 因此,我從命令中刪除了-i
。
$ URLS=(http://example.com/script.cgi?key=value http://example.com/nodotcgi?key=value)
$ SED_OPTIONS=( '-e' 's/\.cgi?key/\.cgikey/g' )
$ printf "%s\n" "${URLS[@]}" | bsd-sed "${SED_OPTIONS[@]}"
http://example.com/script.cgikey=value
http://example.com/nodotcgi?key=value
$ printf "%s\n" "${URLS[@]}" | gnu-sed "${SED_OPTIONS[@]}"
http://example.com/script.cgikey=value
http://example.com/nodotcgi?key=value
$ SED_OPTIONS=( '-e' 's/\.cgi\?key/\.cgikey/g' )
$ printf "%s\n" "${URLS[@]}" | bsd-sed "${SED_OPTIONS[@]}"
http://example.com/script.cgikey=value
http://example.com/nodotcgi?key=value
$ printf "%s\n" "${URLS[@]}" | gnu-sed "${SED_OPTIONS[@]}"
http://example.com/script.cgi?key=value
http://example.com/nodotcgi?key=value
$
請注意,當問號前有反斜杠時,兩個版本的sed
行為有所不同(示例的第二部分)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.