在sed bash脚本变量中转义问号字符

use*_*107 5 regex bash sed

我有一组保存的 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
Run Code Online (Sandbox Code Playgroud)

如何使用 SED_OPTIONS 变量获得完整的命令?

mkl*_*nt0 6

在变量中存储选项和参数列表最安全方法是使用数组

还:

  • 您使用的是基本正则表达式(无-r-E选项),因此?不是特殊字符。并且不需要逃避。
  • 在不是正则表达式的替换字符串中,不要转义.
  • 不需要 option 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
Run Code Online (Sandbox Code Playgroud)

同样,使用数组作为输入文件列表会更安全。$FILES仅当单个文件名不包含嵌入的空格或其他受 shell 扩展影响的元素时才有效。

一般来说:

  • 引号字符串文字,例如sed这里的脚本 - 以防止 shell 解释它们。
  • 引号变量引用,以防止 shell 对它们执行额外的操作,例如路径名扩展(通配)和分词(通过空格拆分为多个标记)。