【发布时间】:2010-12-09 08:18:26
【问题描述】:
我在一行中有一些数据,如下所示
abc edf xyz rfg yeg udh
我想将数据呈现如下
abc
xyz
yeg
edf
rfg
udh
以便替代字段以换行符分隔打印。 有没有一种衬里?
【问题讨论】:
我在一行中有一些数据,如下所示
abc edf xyz rfg yeg udh
我想将数据呈现如下
abc
xyz
yeg
edf
rfg
udh
以便替代字段以换行符分隔打印。 有没有一种衬里?
【问题讨论】:
下面的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
【讨论】:
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])'
【讨论】:
另一个 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;
【讨论】:
part,但这正是我想在这里做的事情(grep,但保留通过和失败,每个都在自己返回的数组中) .谢谢。
可惜之前的 perl 答案太长了。这里有两个 perl 单行代码:
echo 'abc edf xyz rfg yeg udh'|
perl -naE '++$i%2 and say for @F; ++$j%2 and say for "",@F'
在旧版本的 perl 上(没有“say”),你可以使用这个:
echo 'abc edf xyz rfg yeg udh'|
perl -nae 'push @{$a[++$i%2]},"$_\n" for "",@F; print map{@$_}@a;'
【讨论】:
只是为了比较,这里有一些 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 想出了另一种方法,请随时添加它。
【讨论】:
另一个 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], "");'
【讨论】:
这是过于字面化、不可扩展、超短的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
【讨论】:
我在 haskell 中的尝试:
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>
【讨论】:
你也可以只使用 tr:
echo "abc edf xyz rfg yeg udh" | tr ' ' '\n'
【讨论】:
用于比较的 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
【讨论】:
$ 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
对于换行符,我留给你自己做。
【讨论】:
这里还有另一种方法,使用 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
干杯!
【讨论】: