[英]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.