簡體   English   中英

sed bash腳本變量中的轉義問號字符

[英]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解釋它們。
  • 引號變量引用 ,以防止外殼程序對其執行其他操作,例如路徑名擴展(globbing)和字詞拆分(由空格拆分為多個標記)。

我建議將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-sedbsd-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.

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