在匹配后替换行中所有出现的字符

时间:2015-09-09 15:37:53

标签: regex bash perl sed

我有各种各样的行:

   12 0.185861000 4294967296 STATE A variable name
   12 0.187326000 4294967296 STATE Another variable name
   12 0.187629000 4294967296 STATE Another variable name
   12 0.187823000 4294967296 STATE A variable name

我需要转变为

   12 0.185861000 4294967296 STATE A_variable_name
   12 0.187326000 4294967296 STATE Another_variable_name
   12 0.187629000 4294967296 STATE Another_variable_name
   12 0.187823000 4294967296 STATE A_variable_name

然而,"变量名称"出现在不包含" STATE"的行中,并且不应在那里删除空格。显然,之前有空格"变量名称"在包含" STATE"的行中,也不应删除。

所以我需要在" STATE"之后替换所有行中的所有空格。我想到了类似的东西:

perl -pi -e "s/\h/_/g if /^.+STATE\h/" $1

但是,它取代了#34; STATE"之前的空格。当然还有像

这样的东西
perl -pi -e "s/^(.+STATE\h)(.*)\h/\1\2_/g" $1

在" STATE"之后仅替换第一个空白区域。任何提示?我找不到任何东西,可能是因为对此类搜索的查询有点模糊。

4 个答案:

答案 0 :(得分:2)

使用sed:

sed ':a;s/\(STATE [^ ]*\) /\1_/;ta;' file

细节:

:a                       # define a label "a"
s/\(STATE [^ ]*\) /\1_/  # replace the first space after "STATE "
ta                       # go to label "a" if something is replaced

使用perl的一种方法:(使用\G锚来确保连续性)

perl -pi -e 's/(?:\G(?!\A)|STATE\h)\S*\K\h/_/g'

perl的另一种方式:(空格只在组1中替换)

perl -pi -e 's/STATE\h\K(.+)/$1=~s#\h#_#gr/e'

答案 1 :(得分:1)

这个awk应该适用于此:

awk 'p=index($0, " STATE ") {s=substr($0, p+7); gsub(/ /, "_", s); $5=s; NF=5} 1' file
12 0.185861000 4294967296 STATE A_variable_name
12 0.187326000 4294967296 STATE Another_variable_name
12 0.187629000 4294967296 STATE Another_variable_name
12 0.187823000 4294967296 STATE A_variable_name
完成

$5=s以将更改后的值分配回$0并完成NF=5以删除旧值。

答案 2 :(得分:1)

使用GNU AWK

awk -F"STATE " '{gsub(" ","_",$2);print $1"STATE "$2}' <file>

使用&#34; STATE&#34;分割输入作为FS并从$ 2替换空间。您可以使用&#34; [[:space:]]&#34;如果你有标签和空格

您可以使用

awk -F"STATE " '{gsub(" ","_",$2);print}' <file>

但是这会在STATE之后引入额外的一个空格

答案 3 :(得分:1)

使用perl,我可能会像这样解决它:

#!/usr/bin/env perl

use strict;
use warnings;

#read a line
while ( my $line = <DATA> ) {
    #split the first 5 fields into @stuff
    my @stuff = split( ' ', $line, 5 );
    #transform the whitespace in each field to _
    print join( " ", map { s/ /_/g; $_} @stuff );
}

__DATA__
   12 0.185861000 4294967296 STATE A variable name
   12 0.187326000 4294967296 STATE Another variable name
   12 0.187629000 4294967296 STATE Another variable name
   12 0.187823000 4294967296 STATE A variable name

产生:

12 0.185861000 4294967296 STATE A_variable_name
12 0.187326000 4294967296 STATE Another_variable_name
12 0.187629000 4294967296 STATE Another_variable_name
12 0.187823000 4294967296 STATE A_variable_name

这将剥离前导空格。如果您使用:split ( / /, $line, 8 )进行拆分,则可以保留它。 (你需要8,因为前导空格每个都算作一个字段(右边)。

这可以是单行的:

perl -ne 'print join( " ", map {s/ /_/g; $_} split( ' ', $_, 5 ))' yourfilename