Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 转义sed bash脚本变量中的问号字符_Regex_Bash_Sed - Fatal编程技术网

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

Regex 转义sed bash脚本变量中的问号字符,regex,bash,sed,Regex,Bash,Sed,我有一组保存的html文件,其中包含表单的链接,但我想消除这个问号(附带的故事是firefox讨厌它?并随机将其转换为%3F,我确信有一些神奇的修复,但这是为了另一个问题…) 但是,我认为我的代码导致在bash将选项存储为变量时无法正确读取/保存/处理问号字符 # Doesn't work (no pattern matched) SED_OPTIONS='-i s/\.cgi\?key/\.cgikey/g' # Works e.g. http://mywebsite.com/showfil

我有一组保存的html文件,其中包含表单的链接,但我想消除这个问号(附带的故事是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
    ,因为每行只替换一个引用
#使用单个选项/参数创建数组。
SED_ARGS=('-i''s/\.cgi?key/.cgikey/'))
#用数组调用'sed',注意双引号。
sed“${sed_ARGS[@]}”$文件
类似地,使用数组作为输入文件列表会更安全<代码>$FILES仅在单个文件名不包含嵌入空格或其他受shell扩展约束的元素时才起作用

一般来说:

  • 单引号字符串文本,如此处的
    sed
    脚本,以防止shell解释它们
  • 双引号变量引用,以防止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
认为脚本参数实际上是:

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_选项时使用单引号可确保反斜杠在需要时保留,并且不会在
生效之前放置反斜杠。我的Mac电脑上有GNU
sed
和BSD
sed
;为了清楚起见,我将它们别名为
gnused
bsdsed
。请注意,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的两个版本在行为上的差异。

-is/cgi\?/blah/g
实际上应该给出
http://mywebsite.com/showfile.blahkey=somenumber
。我知道!如果我用SED_OPTIONS='-I s/cgi\?/blah/g'定义它,它会留下问号,但是如果我将选项内联在同一行中,就像我调用SED命令“SED-I s/cgi\?/blah/g$FILES”一样,它会删除问号谢谢你的详细回答-如果你有$SED_OPTIONS=('-e''s/\.cgi key/\.cgikey/\.cgikey/g'))正则表达式中的问号不会被解释为“您需要零个或一个‘i’”而不是问号的实际符号吗?正如您所看到的,答案是‘否’(
不会被解释为一个或多个
i
)。在标准(经典)
sed
regex中,
不是元字符。如果使用扩展正则表达式或类似表达式,则会遇到一组不同的问题,但是基本
sed
应该/确实使用基本正则表达式,而
不是元字符。您知道替换字符串中的点之前的\会产生什么影响吗,由于它不是@mklement0所指出的正则表达式,但当我尝试使用/不使用替换字符串时,我看不到任何行为上的差异?我认为这意味着下一个字符被解释为自身而不是元字符,但替换字符串中的元字符数受到严格限制(在
sed
中有反斜杠本身和换行符
\n
,然后用
\1
等替换捕获,这就很接近了。)因此,
\.
都替换为
。是的;GNU
sed
更一致(与自身)与标准不同的是,
\n
s//
命令的左上和右上意味着一件事,这有点令人恼火。