如果特定字符串不在其前面,则将字符串替换为另一个字符串

时间:2017-06-29 07:04:01

标签: shell unix awk sed

如何更换"如果" to" abc if"在使用shell脚本的多个文件中。但是,如果之前的其他地方,我不想改变?

例如:

if (var3 == 4'h0)
   a =    bvec[0];
else
if (var3 == 4'h1)
a =    bvec[1];

应转换为

abc if (var3 == 4'h0)
   a =    bvec[0];
else
if (var3 == 4'h1)
a =    bvec[1];

请注意: 1.可以有无限空间或者在其他地方和之间有新的界限。 2.文件中还有更多代码 3.我希望更改仅在同一文件中发生。 4.我想将一个文件名列表传递给脚本

我尝试过:

sed -r 's/else[[:blank:]]if/temp1/g;s/if/abc if/g;s/temp1/else if/g' file.v

2 个答案:

答案 0 :(得分:1)

用于多字符RS,gensub()和字边界的GNU awk:

$ awk -v RS='^$' -v ORS= '{
    gsub(/@/,"@A")
    gsub(/#/,"@B")
    $0 = gensub(/\<else(\s+)if\>/,"#\\1#","g")
    gsub(/\<if\>/,"abc &")
    $0 = gensub(/#(\s+)#/,"else\\1if","g")
    gsub(/@B/,"#")
    gsub(/@A/,"@")
    print
}' file
abc if (var3 == 4'h0)
   a =    bvec[0];
else
if (var3 == 4'h1)
a =    bvec[1];

答案 1 :(得分:0)

以下是如何在Perl中模拟负变量lookbehind正则表达式的示例:

#! /usr/bin/env perl

use strict;
use warnings;

my $str = do { local $/; <> };
$str =~ s/((?:else\s*if|if))/my_subst($1)/ge;
print $str;

sub my_subst {
    my $res = $_[0];
    if ( $_[0] !~ /^else/ ) {
        $res = "abc if";
    }
    return $res;
}

<强>输出

$ p.pl file.txt 
abc if (var3 == 4'h0)
   a =    bvec[0];
else
if (var3 == 4'h1)
a =    bvec[1];

<强>更新

在文件列表中使用inplace-edit:

$^I = '.bak';
$/ = undef;
while (<>) {
    s/((?:else\s*if|if))/my_subst($1)/ge;
    print;
}

然后您可以运行p.pl file*.txt,备份文件将获得.bak后缀。