我想替换输入,
input_string:@include circle-progress(38px,30px,#4eb630)
和输出,
Output_string:@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,而不是正则表达式。 Glob模式的功能明显低于正则表达式(并且具有非常不同的语法),因此您无法完全按照您的尝试进行操作。好吧,除非你使用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)"
我是否提到延长的球体可能不够优雅?他们在有限的重复中尤其糟糕(正则表达式中的{3,6}
,意思是前一项的3到6之间)。上面的glob以“,#”(显而易见的)开头,然后是三个“[A-Fa-f0-9]”,然后是一个可选的(由?( )
表示)模式,包括另一个十六进制数字和一个可选字符串...... 。 反正你懂这个意思。如果你想简化它并只允许任意数量的十六进制数字,那么它会变得更简单:
replace_glob=', #*([A-Fa-f0-9])'
(顺便说一句,还要注意我在使用它时没有对模式变量进行双重引用 - 这是因为shell将引用的模式(或模式的一部分)视为文字字符串,其中忽略了glob语法。这是其中之一shell中很少有你不应该引用变量引用的情况。)
[root@XXX ~]# a="@include circle-progress(38px, 30px**, #4eb630**)"; echo $a | sed 's/\*\*,.*/)/g'
@include circle-progress(38px, 30px)
你可以使用:
str='input_string: @include circle-progress(38px, 30px, #4eb630)'; echo ${str/, #[A-Fa-f0-9]*/)}
或者用sed:
echo 'input_string: @include circle-progress(38px, 30px, #4eb630)' | sed 's/, #[A-Fa-f0-9]\{3,6\}//'