sed,用行的第一部分全局替换分隔符

时间:2011-07-03 22:46:59

标签: perl sed

假设我有以下几行:

1:a:b:c
2:d:e:f
3:a:b
4:a:b:c:d:e:f

如何使用sed(或perl)编辑它以便阅读:

1a1b1c
2d2e2f
3a3b
4a4b4c4d4e4f

我已经完成了这样的awk:

awk -F':' '{gsub(/:/, $1, $0); print $0}'

但需要很长时间才能完成!所以寻找更快的东西。

3 个答案:

答案 0 :(得分:2)

'有点棘手,但可以使用sed(假设文件data包含示例输入):

$ sed '/^\(.\):/{
s//\1/
: retry
s/^\(.\)\([^:]*\):/\1\2\1/
t retry
}' data
1a1b1c
2d2e2f
3a3b
4a4b4c4d4e4f
$

您可以使用分号将脚本展平为一行; MacOS X上的sed有时会有点胡思乱想并且反对某些部分,所以它被分成6行。第一行匹配以单个字符和冒号开头的行,并在识别时启动一系列操作。第一个替代品,例如,'1:'仅替换'1'。 : retry也是分支的标签 - 这是其中的关键部分。下一个替换将复制第一个冒号上的第一个字符。如果替代品改变了任何东西,t retry会回到标签上。最后一行界定了最初匹配行的整个操作序列。

答案 1 :(得分:2)

#!/usr/bin/perl
use warnings;
use strict;

while (<DATA>) {
    if ( s/^([^:]+)// ) {
        my $delim = $1;
        s/:/$delim/g;
    }
    print;
}

__DATA__
1:a:b:c
2:d:e:f
3:a:b
4:a:b:c:d:e:f

答案 2 :(得分:1)

use feature qw/ say /;
use strict;
use warnings;
while( <DATA> ) {
    chomp;
    my @elements = split /:/;
    my $interject = shift @elements;
    local $" = $interject;
    say $interject, "@elements";
}

__DATA__
1:a:b:c
2:d:e:f
3:a:b
4:a:b:c:d:e:f

或者在linux shell命令行上:

perl -aF/:/ -pe '$i=shift @F;$_=$i.join $i,@F;' infile.txt