Если вы знаете, рисунок на каждом из двух линий, которые вы хотите поменять, но не полное содержимое строк, вы можете сделать что-то вроде этого:
sed -n ' # turn off default printing
/dog/{ # if the line matches "dog"
h # put it in hold space
:a # label "a" - the top of a loop
n # fetch the next line
/something/{ # if it matches "something"
p # print it
x # swap hold and pattern space
bb # branch out of the loop to label "b"
} # done with "something"
# if we're here, the line doesn't match "something"
H # append pattern space to hold space
x # swap hold and pattern space
s/\([^\n]*\)\n\([^\n]*\)$/\2\n\1/ # see below
x # swap hold and pattern space
ba # branch to the top of the loop to label "a"
} # done with "dog"
:b # label "b" - outside the loop
# print lines that don't match and are outside the pair
p # also prints what had been accumulating in hold space
' inputfile
картины замещения держит «собаку» в конце накопленных линий. Он продолжает заменять последние две строки, которые мы держим в удержании, чтобы «собака» «пузырилась» на дно.
Например, давайте поместим еще одну строку после строки «cat», чтобы процесс был немного яснее. Мы будем игнорировать строки перед «собакой» и после «что-то». И я по-прежнему относятся к линиям, используя мои прозвища
this is a dog
this is a cat
there's a bear here, too
this is something else
«Собака» читается, то «кошка» забирается. Некоторые добавления и замены выполняются. Теперь картина пространство выглядит следующим образом (\N
представляет собой символ новой строки, я использую верхний регистр «N», так что выделяется, то ^
является началом шаблона и $
конца):
^this is a dog\Nthis is a cat$
Команда подстановки ищет любое количество символов, которые не являются символами новой строки (и захватывает их), за которыми следует новая строка, за которой следует любое количество символов, которые не являются символами новой строки (и захватывают их), которые находятся в конце строки ($), и заменяет все это с двумя захваченными строками в обратном порядке, разделенными новой строкой. Теперь пространство в пространстве выглядит так:
^this is a cat\Nthis is a dog$
Теперь мы поменяем местами и прочитаем новую строку. Это не «что-то» так мы делаем некоторые добавление и замена и теперь мы имеем:
^this is a cat\Nthis is a dog\Nthere's a bear here, too$
Мы делаем замену снова и получить:
^this is a cat\Nthere's a bear here, too\Nthis is a dog$
Почему мы не получили «медведь/собака/кот "? Поскольку шаблон регулярного выражения, состоящий из двух строк (каждый из которых, как обычно, состоит из не-новых строк, за которым следует новая строка), привязан в конце строки, используя $
, поэтому мы игнорируем все, что приходит перед ним.Обратите внимание, что последняя строка новой строки подразумевается и фактически не существует в шаблоне или пространстве удержания. Вот почему я не показываю его здесь.
Теперь мы читаем «что-то» и печатаем его. Мы поменяемся местами. Привет! есть вещи, которые мы «пузырялись». Филиал и печать. Так как «собака» находится в нижней части строк (которые были накоплены в удержании), и мы напечатали «что-то» прямо перед этой связкой, эффект заключается в том, что мы поменяли местами две линии.
Этот скрипт будет работать независимо от того, сколько строк отображается до, между двумя или после двух строк, подлежащих обмену. Фактически, если имеется несколько пар совпадающих строк, члены каждой пары будут обмениваться по всему файлу.
Как вы можете видеть, я использую только одно слово в интересующих вас строках, но любое подходящее регулярное выражение будет делать.
+1 для замечательных комментариев. – galaxywatcher 2012-01-30 13:57:30