假设有一个bash变量保存了以下字符串:
INPUT="Cookie: cf_clearance=foo; __cfduid=bar;"
为什么替换
${INPUT/cf_clearance=[^;]*;/}
产生的输出是Cookie:
,而不是我期望的Cookie: __cfduid=bar;
?在在线正则表达式验证器中测试相同的正则表达式可以确认
cf_clearance=[^;]*;
只匹配cf_clearance=foo;
而不匹配字符串的其余部分。我在这里做错了什么?
假设有一个bash变量保存了以下字符串:
INPUT="Cookie: cf_clearance=foo; __cfduid=bar;"
${INPUT/cf_clearance=[^;]*;/}
产生的输出是Cookie:
,而不是我期望的Cookie: __cfduid=bar;
?cf_clearance=[^;]*;
只匹配cf_clearance=foo;
而不匹配字符串的其余部分。使用实际的正则表达式匹配功能而不是与模式一起工作的参数扩展。
[[ $INPUT =~ (.*)(cf_clearance=[^;]*;)(.*) ]]
ans=${BASH_REMATCH[1]}${BASH_REMATCH[3]}
您也可以使用扩展模式,它在功能上与正则表达式等效:
shopt -s extglob
$ echo "${INPUT/cf_clearance=*([^;]);/}"
dash
、ksh
、zsh
等)中无法工作。问题专门针对Bash,因此这不是答案的问题,但需要注意。 - Zac Bksh
和zsh
都有解决方案可用(可能与bash
的解决方案没有太大区别),而POSIX shell则需要多次使用expr
命令。 - chepner使用sed
:
INPUT=$(sed 's/cf_clearance=[^;]*;//' <<< "$INPUT")
像评论中所说的那样,Bash参数替换仅支持glob模式,而不是正则表达式。因此问题实际上在于您的期望,而不是代码本身。
如果您知道表达式可以锚定到字符串开头,您可以使用${INPUT#prefix}
参数替换来获取最短可能的匹配,并在前面添加回Cookie:
:
echo "Cookie: ${INPUT#Cookie: cf_clearance=*;}"
cf_clearance
之前的部分,找到在 cf_clearance
分号后面的部分;将它们粘合在一起即可。head=${INPUT%cf_clearance=*}
tail=${INPUT#*cf_clearance=*;}
echo "$head$tail"
echo "${INPUT%cf_clearance=*}${INPUT#*cf_clearance=*;}"
这对于我这样老练的口味来说,有点过于密集了。
${MYVAR//[a-z]/X}
这样更简单的模式可以工作。 - Oscar Hierroprintf()
和scanf()
支持(如果你编写 C 程序)。 - iBug