使用sed,我可以只更改一行的正则表达式匹配部分吗?

问题描述:

我可以将字符串替换限制为与正则表达式匹配的行的一部分吗?使用sed,我可以只更改一行的正则表达式匹配部分吗?

例如:

A this matches Z this does not 

而且,我想和that但只有内子通过匹配替换this

A[^Z]*Z 

即,该线的唯一部分,其可以是如下所示以粗体显示:

A this match Z this doe不是

所以,我正在寻找的结果是:

A that matches Z this does not 

但是,看到的东西,我试图在整条线路运营的实际效果:

% sed '/A[^Z]*Z/ { 
    s/this/that/g 
    }' <<<"A this matches Z this does not" 
A that matches Z that does not 
% 

的上面的例子是为了说明的目的。

回顾:是否有使用sed进行更改到线的正则表达式匹配部分的任何通用的解决方案?如果答案是“否”,那么是否有解决方案只使用安装在CentOS 7最小配置中的软件(如awk)?另外,我不想依赖第三方软件包。

我的环境:

  • 的CentOS 7.3内核3.10.0-514.6.1.el7.x86_64]
  • 的sed(GNU SED)4.2.2 [沉渣 - 4.2.2-5。 el7.x86_64]
  • 击4.2.46(1)[bash的-4.2.46-21.el7_3.x86_64]
+0

做你有perl? 'echo'这个匹配Z这不是'| perl -pe's/A [^ Z] * Z/$&=〜s | this | that | gr/ge'' – Sundeep

+1

如果您想要一个不知道文件内容知识的通用解决方案,那么你需要在第一个单词,第四个单词等中指定类似_start的东西,因为你提供了一个模式为“A”的问题,所以'Z'的答案倾向于使用这种方式。 – Inian

+0

是的,我正在寻找一个通用的解决方案。替换可以在任何行上完成,但是替换候选项的唯一部分是匹配给定正则表达式的那些部分。所以,要求包括2个部分:(1)正则表达式;和(2)要应用于与正则表达式匹配的任何行的部分的转换。 –

如果perl可用:

$ echo 'A this matches Z this does not' | perl -pe 's/A[^Z]*Z/$&=~s|this|that|gr/ge' 
A that matches Z this does not 
  • g改性剂来代替匹配的文本
  • e评价改性剂中出现的所有允许使用Perl代码在替代
  • $&=~s|this|that|gr表达的替换部分,以仅在匹配的文本进行替换,r改性剂还给结果而不改变$&

延伸阅读:

+0

非常感谢一个有效的解决方案。 –

可以使用带有捕获组正则表达式的行的一部分匹配你想要,并且只替换它的一部分。

sed 's/\(A[^Z]*\)this\([^Z]*Z\)/\1that\2/' 
+0

这是一个需要知道文件内容的特定解决方案。我需要一个通用解决方案。但是,谢谢。 –

+1

这需要预先知道的唯一特定词是'this'和'that',如果您的目标是用'that'替换'this',这就像'sed'可以消化一样。我在这里错过了什么吗? –

+0

@DavidC。Rankin如果不在'A'和'Z'之间,他不想替换'this'。 – Barmar

用下面的办法:

echo "A this matches Z this does not" | sed -r 's/(A[^Z]*)\bthis\b([^Z]*Z)/\1that\2/g' 

输出:

A that matches Z this does not 
+0

这就要求将正则表达式分解,对吧?也就是说,我认为解决方案需要具体的正则表达式知识。 –

+1

@SteveAmerige,你写*只是与正则表达式匹配的一部分* - 我们如何在不知道正则表达式的情况下编写正则表达式? – RomanPerekhrest

+0

围绕'\ bthis \ b'的捕获组的原因是什么? – Barmar

如果你可以使用是sed,可以在bash做过这样的:

#!/bin/bash 
str="This does not A this matches Z this also does not" 

regex='^\(.*\)\(A[^Z]*Z\)\(.*\)$' 

a=$(sed -e 's/'"$regex"'/\1/' <<<"$str") 
b=$(sed -e 's/'"$regex"'/\2/' -e 's/this/that/g' <<<"$str") 
c=$(sed -e 's/'"$regex"'/\3/' <<<"$str") 

echo "$a$b$c" 

或者,您可以用awk(快):

#!/bin/bash 

str="This does not A this matches Z this also does not" 

awk -vreg='A[^Z]*Z' '{ 
split($0,a,reg,s); 
printf("%s%s%s\n",a[1],gensub(/this/,"that","g", s[1]),a[2]) 
}' <<<"$str" 
+0

我喜欢这里的想法。但是,试一下这个测试用例:'str =“A匹配Z和A这也匹配Z这不是”'在sed方法中只做一个替换,并且只产生'在awk方法中匹配Z和'的A。 –