Как переключать / вращать каждые две строки с помощью sed / awk? - PullRequest
12 голосов
/ 25 июля 2011

Я делал это вручную, и я просто не могу больше это делать - у меня тысячи строк, и я думаю, что это работа для sed или awk.

По сути, у нас есть файл, подобный этому:

A sentence X
A matching sentence Y
A sentence Z
A matching sentence N

Этот шаблон продолжается для всего файла.Я хочу перевернуть каждое предложение и соответствующее предложение, чтобы весь файл получился таким:

A matching sentence Y
A sentence X
A matching sentence N
A sentence Z

Есть какие-нибудь советы?

edit: расширение исходной задачи

Dimitre Radoulov предоставил отличный ответ для исходной задачи.Это расширение основной проблемы - некоторые подробности:

Допустим, у нас есть организованный файл (из-за строки sed, которую дал Димитр, файл организован).Однако теперь я хочу организовать файл в алфавитном порядке, но только с использованием языка (английский) второй строки.

watashi 
me
annyonghaseyo
hello
dobroye utro!
Good morning!

Я хотел бы организовать в алфавитном порядке с помощью английских предложений (каждое второе предложение).Учитывая приведенный выше ввод, это должен быть вывод:

dobroye utro!
Good morning!
annyonghaseyo
hello
watashi
me 

Ответы [ 4 ]

16 голосов
/ 25 июля 2011

Для первой части вопроса, вот один из способов поменять каждую другую строку друг с другом в sed без использования регулярных выражений:

sed -n 'h;n;p;g;p'

Командная строка -n подавляет автоматическую печать,Команда h копирует текущую строку из пространства шаблона в пространство удержания, n читает следующую строку в пространство шаблона и печатает ее p;g копирует первую строку из пространства удержания обратно в пространство шаблона, возвращая первую строку обратно в пространство шаблона, и p печатает ее.

9 голосов
/ 25 июля 2011
sed 'N; 
s/\(.*\)\n\(.*\)/\2\
\1/' infile

N - добавить следующую строку ввода в пространство шаблона
\(.*\)\n\(.*\) - сохранить совпадающие части пространства шаблона как перед, так и после новой строки.
\2\\ \1 - заменить две строки (\ 1 - первая сохраненная часть, \ 2 - вторая).Используйте экранированный буквенный символ новой строки для переносимости

В некоторых реализациях sed вы можете использовать escape-последовательность \ n: \2\n\1.

5 голосов
/ 25 июля 2011

Первый вопрос:

awk '{x = $0; getline; print; print x}' filename

следующий вопрос: сортировка по 2-й строке

paste - - < filename | sort -f -t $'\t' -k 2 | tr '\t' '\n'

, которая выводит:

dobroye utro!
Good morning!
annyonghaseyo
hello
watashi
me
1 голос
/ 25 июля 2011

Предполагая, что входной файл выглядит следующим образом:

A sentence X
Z matching sentence Y
A sentence Z
B matching sentence N
A sentence Z
M matching sentence N

Вы можете выполнять как обмен, так и сортировку с помощью Perl :

perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort keys %_; 
   }' infile

Вывод, который я получаю:

% perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort keys %_;
   }' infile
B matching sentence N
A sentence Z
M matching sentence N
A sentence Z
Z matching sentence Y
A sentence X

Если вы хотите заказать по первой строке (до обмена):

perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort {
      $_{ $a } cmp $_{ $b }
      } keys %_; 
   }' infile

Итак, если оригинальный файл выглядит так:

% cat infile1
me
watashi 
hello
annyonghaseyo
Good morning!
dobroye utro!

Вывод должен выглядеть следующим образом:

% perl -lne'
 $_{ $_ } = $v unless $. % 2;
 $v = $_;
 END {
  print $_, $/, $_{ $_ }
    for sort {
  $_{ $a } cmp $_{ $b }
  } keys %_;
   }' infile1
dobroye utro!
Good morning!
annyonghaseyo
hello
watashi 
me

Эта версия должна корректно обрабатывать дубликаты записей:

perl -lne'
 $_{ $_, $. } = $v unless $. % 2;
 $v = $_;
 END {
    print substr( $_, 0, length() - 1) , $/, $_{ $_ }
    for sort {
      $_{ $a } cmp $_{ $b }
      } keys %_; 
   }' infile

И еще одна версия, вдохновленная решением, опубликованным Гленном (включая обмен записями)и предполагая, что шаблон _ZZ_ отсутствует в текстовом файле):

sed 'N; 
  s/\(.*\)\n\(.*\)/\1_ZZ_\2/' infile | 
    sort |
      sed 's/\(.*\)_ZZ_\(.*\)/\2\
\1/'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...