开发者

sed, replace globally a delimiter with the first part of the line

Lets say I have the following lines:

1:a:b:c
2:d:e:f
3:a:b
4:a:b:c开发者_开发技巧:d:e:f

how can I edit this with sed (or perl) in order to read:

1a1b1c
2d2e2f
3a3b
4a4b4c4d4e4f

I have done with awk like this:

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

but takes ages to complete! So looking for something faster.


'Tis a tad tricky, but it can be done with sed (assuming the file data contains the sample input):

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

You may be able to flatten the script to one line with semi-colons; sed on MacOS X is a bit cranky at times and objected to some parts, so it is split out into 6 lines. The first line matches lines starting with a single character and a colon and starts a sequence of operations for when that is recognized. The first substitute replaces, for example, '1:' by just '1'. The : retry is a label for branching too - a key part of this. The next substitution copies the first character on the line over the first colon. The t retry goes back to the label if the substitute changed anything. The last line delimits the entire sequence of operations for the initially matched line.


#!/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


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

Or on the linux shell command line:

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜