bash,定期表达的问题

时间:2015-07-22 05:14:07

标签: regex bash sed

给出以下句子:“我的#1例子!”,在bash中我想用'test'替换'my'(我的包括)之前的所有内容。 我在做:

echo "something my #1 example!" | sed s/.+my/test/g

预期结果应为:

test #1 example!

但实际结果是:

something my #1 example!

我假设它找不到匹配的表达式,即使它在这里工作:http://regexr.com/3beg4

2 个答案:

答案 0 :(得分:3)

对于GNU sed(最可能的情况),您需要使用扩展正则表达式(带有-r--regexp-extended标志之一),或者如果您使用+则转义想继续使用基本的正则表达式。

有关详细信息,请参阅以下文字:

pax> echo "something my #1 example!" | sed 's/.+my/test/g'
something my #1 example!

pax> echo "something my #1 example!" | sed -r 's/.+my/test/g'
test #1 example!

pax> echo "something my #1 example!" | sed 's/.\+my/test/g'
test #1 example!

根据sed信息页面:

  

基本和扩展正则表达式之间的唯一区别在于几个字符的行为:'?''+',括号,大括号'{}''|'。< / p>      

虽然基本正则表达式要求对它们进行转义(如果您希望它们表现为特殊字符),使用扩展正则表达式时,如果希望它们匹配文字字符,则必须将它们转义

如果您没有使用具有此级别支持的sed,则通常可以将'.+'转换为'..*'以达到相同的效果。

答案 1 :(得分:0)

你在问题​​标题中说bash正则表达式,然后写了一些关于sed的内容。以下是如何在纯粹的bash中做到这一点:

foo="something my #1 example!";
while [[ $foo =~ (.+my)(.*) ]]; do    # loop instead of if, for /g.
    foo="test${BASH_REMATCH[2]}";
    #  If your pattern can match the replacement, then just loop over BASH_REMATCH[2]
done;
echo "$foo"

Bash没有替换正则表达式运算符,因此您必须通过在要修改的部分之前/之后捕获(.*)来模拟它。

如果要修改shell变量中的字符串,这可能比sed更有效。如果您只是将stdin过滤到stdout,那么sed会保存您编写read循环,并且bash在处理大型文本流时要比sed / grep慢得多。