我要替换输入,
输入字符串:@include circle-progress(38px, 30px, #4eb630)
和输出,
输出字符串:@include circle-progress(38px, 30px)
使用 ${input_string//pattern/replacement_string}
其中模式是 , #[A-Fa-f0-9]{3,6}
我供应。
这个模式匹配我在regex101.com测试时要替换的部分,但是代码
replace_pat=", \#[A-Fa-f0-9]{3,6}"
echo "${input_string//"$replace_pat"/}"
输出完全相同的输入。我不想使用任何其他东西,比如 sed。不知道我哪里出错了。
已解决。谢谢戈登。
使用 glob 模式的解决方案工作得很好,但现在下面的代码仍然打印完全相同的输入,即 line
匹配pattern
,当我从文件中读取代码行时。
pattern="@include circle-progress\(([0-9]{1,3}px, ){2}#[A-Fa-f0-9]{3,6}\)"
replace_glob=', #[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]?([A-Fa-f0-9]?([A-Fa-f0-9]?([A-Fa-f0-9])))'
while IFS='' read -r line || [[ -n "$line" ]]; do
if [[ $line =~ $pattern ]]
then
echo "${line//$replace_glob/}"
fi
done < "$1"
最佳答案
您正在使用的模式替换 (${var//pattern/replacement}
) 使用 glob patterns ,不是正则表达式。全局模式明显不如正则表达式强大(并且具有非常不同的语法),因此您不能完全做您想做的事情。好吧,除非您使用 bash(不是通用的 POSIX shell)并启用扩展的 glob 模式。它们的语法与正则表达式非常不同,但实际上它们同样强大(但有时不够优雅)。以下是如何在 bash 中执行此操作:
shopt -s extglob # Enable extended glob pattern syntax
replace_glob=', #[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]?([A-Fa-f0-9]?([A-Fa-f0-9]?([A-Fa-f0-9])))'
input_string='@include circle-progress(38px, 30px, #4eb630)'
echo "${input_string//$replace_glob/}" # prints "@include circle-progress(38px, 30px)"
我有没有提到扩展的 glob 可能不够优雅?它们在有界重复方面尤其糟糕(正则表达式中的 {3,6}
,表示前一项的 3 到 6 之间)。上面的 glob 以“,#”(很明显)开头,然后是三个“[A-Fa-f0-9]”,然后是一个可选的(由 ?( )
表示)模式,其中包括另一个十六进制数字和一个可选的字符串......好吧,你明白了。如果您想简化它并只允许任意数量的十六进制数字,那么它会变得更加简单:
replace_glob=', #*([A-Fa-f0-9])'
(顺便说一句,还要注意我在使用模式变量时没有用双引号引起来——那是因为 shell 将引用的模式(或模式的一部分)视为文字字符串,其中忽略了 glob 语法。这是shell 中您不应该双引号变量引用的少数情况之一。)
关于linux - Bash:仅使用参数扩展查找和替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47920600/