如何拆分线并重新排列其元素?

时间:2009-10-23 04:52:44

标签: perl unix shell sed awk

我在一行上有一些数据,如下所示

abc edf xyz rfg yeg udh

我想提供如下数据

abc
xyz
yeg


edf
rfg
udh

以便用换行符分隔打印备用字段。 这个有衬里吗?

12 个答案:

答案 0 :(得分:6)

以下awk脚本可以执行此操作:

> echo 'abc edf xyz rfg yeg udh' | awk '{
    for (i = 1;i<=NF;i+=2){print $i}
    print "";
    for (i = 2;i<=NF;i+=2){print $i}
    }'
abc
xyz
yeg

edf
rfg
udh

答案 1 :(得分:4)

Python与上面的awk(4行)具有相同的精神:

$ echo 'abc edf xyz rfg yeg udh' | python -c 'f=raw_input().split()
> for x in f[::2]: print x
> print
> for x in f[1::2]: print x'

Python 1-liner(省略与之相同的管道):

$ python -c 'f=raw_input().split(); print "\n".join(f[::2] + [""] + f[1::2])'

答案 2 :(得分:3)

另一个Perl 5版本:

#!/usr/bin/env perl
use Modern::Perl;
use List::MoreUtils qw(part);

my $line = 'abc edf xyz rfg yeg udh';

my @fields = split /\s+/, $line; # split on whitespace

# Divide into odd and even-indexed elements
my $i = 0;
my ($first, $second) = part { $i++ % 2 }  @fields;

# print them out
say for @$first;
say '';          # Newline
say for @$second;

答案 3 :(得分:3)

以前的perl答案很长很遗憾。这是两个perl单行:

echo 'abc edf xyz rfg yeg udh'|
  perl -naE '++$i%2 and say for @F; ++$j%2 and say for "",@F'

在旧版本的perl上(没有“说”),您可以使用:

echo 'abc edf xyz rfg yeg udh'|
  perl -nae 'push @{$a[++$i%2]},"$_\n" for "",@F; print map{@$_}@a;'

答案 4 :(得分:2)

仅仅为了比较,这里有一些Perl脚本(毕竟TMTOWTDI)。一种相当实用的风格:

#!/usr/bin/perl -p

use strict;
use warnings;

my @a = split;
my @i = map { $_ * 2 } 0 .. $#a / 2;
print join("\n", @a[@i]), "\n\n",
      join("\n", @a[map { $_ + 1 } @i]), "\n";

我们也可以更接近AWK脚本:

#!/usr/bin/perl -p

use strict;
use warnings;

my @a = split;
my @i = map { $_ * 2 } 0 .. $#a / 2;
print "$a[$_]\n" for @i;
print "\n";
print "$a[$_+1]\n" for @i;

我已经没有办法做到这一点,所以如果任何其他聪明的Perlers想出另一种方法,请随意添加它。

答案 5 :(得分:1)

另一个Perl解决方案:

use strict;
use warnings;

while (<>)
{
    my @a = split;
    my @b = map { $a[2 * ($_%(@a/2)) + int($_ / (@a /2))]  . "\n" } (0 .. @a-1); 
    print join("\n", @a[0..((@b/2)-1)], '', @a[(@b/2)..@b-1], '');
}

你甚至可以把它浓缩成一个真正的单行:

perl -nwle'my @a = split;my @b = map { $a[2 * ($_%(@a/2)) + int($_ / (@a /2))]  . "\n" } (0 .. @a-1);print join("\n", @a[0..((@b/2)-1)], "", @a[(@b/2)..@b-1], "");'

答案 6 :(得分:1)

这是太文字,不可扩展,超短awk版本:

awk '{printf "%s\n%s\n%s\n\n%s\n%s\n%s\n",$1,$3,$5,$2,$4,$6}'

稍微长一点(另外两个字符),使用嵌套循环(在末尾打印一个额外的换行符):

awk '{for(i=1;i<=2;i++){for(j=i;j<=NF;j+=2)print $j;print ""}}'

不打印额外的换行符:

awk '{for(i=1;i<=2;i++){for(j=i;j<=NF;j+=2)print $j;if(i==1)print ""}}'

为了比较, paxdiablo 的版本删除了所有不必要的字符(1,9或11个字符):

awk '{for(i=1;i<=NF;i+=2)print $i;print "";for(i=2;i<=NF;i+=2)print $i}'

这是一个全Bash版本:

d=(abc edf xyz rfg yeg udh)
i="0 2 4 1 3 5"
for w in $i
do
    echo ${d[$w]}
    [[ $w == 4 ]]&&echo
done

答案 7 :(得分:1)

我在哈斯克尔的尝试:

Prelude> (\(x,y) -> putStr $ unlines $ map snd (x ++ [(True, "")] ++ y)) $ List.partition fst $ zip (cycle [True, False]) (words "abc edf xyz rfg yeg udh")
abc
xyz
yeg

edf
rfg
udh
Prelude>

答案 8 :(得分:0)

你也可以使用tr: echo "abc edf xyz rfg yeg udh" | tr ' ' '\n'

答案 9 :(得分:0)

用于比较的Ruby版本:

ARGF.each do |line|
  groups = line.split
  0.step(groups.length-1, 2) { |x| puts groups[x] }
  puts
  1.step(groups.length-1, 2) { |x| puts groups[x] }
end

ARGF.each do |line|
  groups = line.split
  puts groups.select { |x| groups.index(x) % 2 == 0 }
  puts
  puts groups.select { |x| groups.index(x) % 2 != 0 }
end

答案 10 :(得分:0)

$ echo 'abc edf xyz rfg yeg udh' |awk -vRS=" " 'NR%2;NR%2==0{_[++d]=$0}END{for(i=1;i<=d;i++)print _[i]}'
abc
xyz
yeg
edf
rfg
udh

对于换行,我留给你自己做。

答案 11 :(得分:0)

这是另一种方法,使用Bash,手动重新排列一行中的单词 - 之前转换为数组:

echo 'abc edf xyz rfg yeg udh' | while read tline; do twrds=($(echo $tline)); echo -e "${twrd[0]} \n${twrd[2]} \n${twrd[4]} \n\n ${twrd[1]} \n${twrd[3]} \n${twrd[5]} \n" ; done 

干杯!