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

时间:2017-02-13 08:54:02

标签: regex bash awk sed centos7

我可以将字符串替换限制为与正则表达式匹配的行的一部分吗?

例如:

A this matches Z this does not

并且,我想将this替换为that,但仅限于匹配的子字符串:

A[^Z]*Z

也就是说,可以操作的线的唯一部分如下面粗体所示:

这匹配Z 这不是

所以,我正在寻找结果:

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的常规解决方案仅将更改到一行的正则表达式匹配部分?如果答案是&#34;否,&#34;那么有一个解决方案只使用安装在CentOS 7最小配置中的软件(例如awk)吗?另外,我不想依赖第三方软件包。

我的环境:

  • CentOS 7.3 [kernel-3.10.0-514.6.1.el7.x86_64]
  • sed(GNU sed)4.2.2 [sed-4.2.2-5.el7.x86_64]
  • Bash 4.2.46(1)[bash-4.2.46-21.el7_3.x86_64]

4 个答案:

答案 0 :(得分:1)

您可以使用带有捕获组的正则表达式来匹配所需行的部分,并仅替换其中的一部分。

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

答案 1 :(得分:1)

使用以下方法:

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

答案 2 :(得分:1)

如果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修饰符会在不更改$&的值的情况下返回结果

进一步阅读:

答案 3 :(得分:0)

如果您只能使用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"