替换两个字符串之间的多次出现

时间:2018-01-05 00:23:26

标签: regex bash perl awk sed

我需要用a替换xxzz之间的每个字符hello

#input
a xxab abzz ca xxbczz aaa axxazza xxczzaxxczz
#output
a xxhellob hellobzz ca xxbczz aaa axxhellozza xxczzaxxczz

这适用于一对,它不适用于更多xx/zz对(它取代了第一个a和最后xx之间的每个zz

sed -r ':rep; s/(xx.*)a(.*zz)/\1hello\2/; trep'

我认为最好的方法是使用更高级的正则表达式,例如perl

我正在寻找bashsedawkperl的解决方案。这个任务甚至可以用于基本/扩展正则表达式吗?当对具有更多字符(例如xxxxxx/zzzzzz)时,不会变得难以消化的解决方案是首选。

6 个答案:

答案 0 :(得分:2)

你可以试试这个Perl方法

perl -E '$_="a xxab abzz ca xxbczz aaa axxazza xxczzaxxczz";
s{xx(.+?)zz}{"xx".$1=~s/a/hello/gr."zz"}xge; 
say $_ ; '

解释

s{
   xx(.+?)zz #grouping the content
 }
 {
   "xx".$1=~s/a/hello/gr."zz" #again making the substitution for $1 and concatenating `xx` and `zz`  
 }xge;

标志

g - >全球

r - >非破坏性修饰符

e - > EVAL。

环顾四周

perl -E '$_="a xxab abzz ca xxbczz aaa axxazza xxczzaxxczz";
s{(?<=xx)(.+?)(?=zz)}{$1=~s/a/hello/gr}xge; 
say $_ ; '

答案 1 :(得分:1)

这可能适合你(GNU sed):

sed -r ':a;s/zz/\n/;:b;tb;s/(xx[^\na]*)a([^\n]*\n)/\1hello\2/;tb;/zz/ba;s/\n/zz/g' file

这会将zz替换为换行符,然后替换axx换行符之间的所有hello

N.B。可能会有xxzz未配对的任何a,并且它们之间的任何IWebElement radioButton = driver.FindElement(By.XPath("//*[@type='radio'][1]"); radioButton.Click(); 都将被替换。

答案 2 :(得分:1)

对于仅使用正则表达式的解决方案可能会获得奖励,但这是一个简单的解决方案。

xx拆分字符串。对术语进行迭代,并将每个术语的a替换为zz

我将a替换为-以便于审核。开始和结束模式位于$pb$pe

perl -wE'$_ = q(a xxab abzz ca xxbczz aaa axxazza); say; 
    $pb = qr(xx); $pe = qr(zz); 
    ($r, @t) = split /($pb)/; 
    for (@t) { 
        if (/^$pb$/) { $r.=$_, next }; 
        /(.*?)($pe.*)/; 
        if ($m = $1) { $m =~ s/a/-/g; $r .= $m} 
        $r .= $2 if $2 
    }; say $r
'

这是一种准备测试的形式,但它应该是一个脚本。它打印

a xxab abzz ca xxbczz aaa axxazza
a xx-b -bzz ca xxbczz aaa axx-zza

我已经测试了几个字符串,但无论如何都请测试更多。

这也可以通过正则表达式来完成,但这更先进,更难理解。

答案 3 :(得分:1)

是的,最好使用Perl

perl -pe's/xx(.+?)zz/"xx".$1=~s|a|hello|gr."zz"/ge' file.txt

答案 4 :(得分:0)

问题在于.*,因为.会匹配包括空格在内的每个字符。 您应该使用\S代替所有非空白字符:

$ echo 'a xxababzz ca xxbczz aaa axxazza' | sed -r ':rep; s/(xx\S*?)a(\S*?zz)/\1hello\2/; trep'
a xxhellobhellobzz ca xxbczz aaa axxhellozza

答案 5 :(得分:0)

你必须描述所有不是zz (一个不是zz后跟另一个角色的角色)< / em>在a之前和之后直到zz并使用标签和条件测试来处理该行,直到a和{之间不再有xx为止{1}}:

zz

Perl方式:

sed -E ':a;s/(xx([^z]|z[^z])*z?)a(([^z]|z[^z])*zz)/\1hello\3/g;ta' file

可以轻松更改为:

perl -pe's/(?:\G(?!^)|xx(?=.*zz))[^za]*(?:z(?!z)[^za]*)*\Ka/hello/g' file

处理perl -pe's/(?:\G(?!^)|xxxxxx(?=.*zzzzzz))[^za]*(?:z(?!zzzzz)[^za]*)*\Ka/hello/g' file xxxxxx