2009-10-23 3 views
2

У меня есть некоторые данные по одной линии, как показано нижеКак разделить строку и изменить ее элементы?

abc edf xyz rfg yeg udh 

Я хочу, чтобы представить данные, как показано ниже

abc 
xyz 
yeg 


edf 
rfg 
udh 

так, что чередующиеся поля печатаются с новой строки разделены. Есть ли какие-нибудь вкладыши для этого?

ответ

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 
+0

Пожалуйста, полностью см. Мой вопрос. «Дополнительные поля печатаются с помощью новой строки» – Vijay

+0

Нетерпеливая мелочь, не так ли? :-) Я предполагаю, что теперь вы измените этот downvote, чтобы ответ был правильным. – paxdiablo

+0

Спасибо за это :-) Привет. – paxdiablo

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-вкладыш (опуская трубку к нему который идентичен):

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

«Другой ответ был отправлен» не появился. Рад узнать, что я не единственный, у кого была эта идея. Python имеет более удобный синтаксис разрезания массива. Это (IMHO) одно из самых раздражающих пропусков с Perl (это и индексация строк). –

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 придумать другой метод, не стесняйтесь добавлять его.

0

вы также можете просто использовать Tr: echo "abc edf xyz rfg yeg udh" | tr ' ' '\n'

+0

Это не сработает. OP хочет, чтобы поля были перегруппированы. –

+0

Это просто заменяет пробелы новыми символами; печать полей в порядке на отдельных строках - это не то, что ищет плакат. –

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)[email protected]], ''); 
} 

Вы даже могли конденсироваться его в настоящий однострочника:

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)[email protected]], "");' 
+0

Слишком много гольфа, недостаточно работы! –

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}' 

Вот все-Баш версия:

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 
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; 
+1

Я никогда не замечал 'part', но это именно то, что я хотел сделать здесь (' grep', но сохранить как проходы, так и неудачные, каждый в своем собственном возвращенном массиве). Благодарю. – Telemachus

0

Рубин версии для сравнения:

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 
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;' 
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 

для переноса строк, я оставляю вам делать сами.

1

Моя попытка в 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> 
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 

Ура!

+0

Это ограничивает всего 5 слов в строке, и если количество слов увеличивается. Это не сработает. Я просто показал пример, и это не всегда одно и то же. – Vijay

+0

В оригинальной постановке проблемы ничего не говорится о «количестве слов». Приветствия! – sdaau

Смежные вопросы