Wie aufgeteilt ich eine Linie nach oben und seine Elemente neu anordnen?
Frage
Ich habe einige Daten auf einer einzigen Zeile wie unten
abc edf xyz rfg yeg udh
Ich möchte die Daten wie unten
präsentierenabc
xyz
yeg
edf
rfg
udh
, so dass abwechselnde Felder mit gedruckten Neuen-Zeile getrennt. Gibt es einen Liner für das?
Lösung
Das folgende awk
Skript kann es tun:
> 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
Andere Tipps
Python im gleichen Geist wie die oben awk (4 Zeilen):
$ 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'
1 Python-Liner (Weglassen des Rohrs, um es die identisch ist):
$ python -c 'f=raw_input().split(); print "\n".join(f[::2] + [""] + f[1::2])'
Eine weitere Perl-5-Version:
#!/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;
Schade, dass die bisherigen Perl Antworten so lang sind. Hier sind zwei Perl-Einzeiler:
echo 'abc edf xyz rfg yeg udh'|
perl -naE '++$i%2 and say for @F; ++$j%2 and say for "",@F'
Bei älteren Versionen von Perl (ohne "sagen"), können Sie diese verwenden:
echo 'abc edf xyz rfg yeg udh'|
perl -nae 'push @{$a[++$i%2]},"$_\n" for "",@F; print map{@$_}@a;'
Nur zum Vergleich, hier ein paar Perl-Skripte es (TMTOWTDI, nachdem alle) zu tun. Ein eher funktionaler Stil:
#!/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";
Wir könnten auch tun es näher an den AWK-Skript:
#!/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;
Ich habe aus Wege laufen, es zu tun, so dass, wenn andere kluge Perlers mit einem anderen Verfahren kommen, fühlen sich frei, um es hinzuzufügen.
Eine weitere Perl-Lösung:
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], '');
}
Sie könnten sogar verdichten es zu einem echten Einzeiler:
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], "");'
Hier ist die allzu wörtliche, nicht skalierbare, ultrakurze awk
Version:
awk '{printf "%s\n%s\n%s\n\n%s\n%s\n%s\n",$1,$3,$5,$2,$4,$6}'
Etwas länger (zwei Zeichen), mit verschachtelten Schleifen (drucken eine zusätzliche Newline am Ende):
awk '{for(i=1;i<=2;i++){for(j=i;j<=NF;j+=2)print $j;print ""}}'
Ist eine zusätzliche Newline nicht gedruckt:
awk '{for(i=1;i<=2;i++){for(j=i;j<=NF;j+=2)print $j;if(i==1)print ""}}'
Zum Vergleich: paxdiablo 's-Version mit allen unnötigen Zeichen entfernt (1, 9 oder 11 mehr Zeichen):
awk '{for(i=1;i<=NF;i+=2)print $i;print "";for(i=2;i<=NF;i+=2)print $i}'
Hier ist eine All-Bash-Version:
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
Mein Versuch in 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>
Sie könnten auch nur tr verwenden:
echo "abc edf xyz rfg yeg udh" | tr ' ' '\n'
Ruby-Versionen zum Vergleich:
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
Für Zeilenumbrüche, ich überlasse es Ihnen selbst zu tun.
Hier ist noch eine andere Art und Weise, mit Bash, manuell Wörter in einer Zeile neu ordnen - mit früheren Umwandlung in ein Array:
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
Cheers!