Я только что это пережил и не смог понять.
sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\nblub/ p }' file.
где находится файл cat:
foo
foo
bar
почему есть 1!H
, потому что для меня это 1h
перезаписывает пространство шаблонов и 1!H
бесполезно
Но однострочник sed, похоже, работает нормально.
решение1
Видеть@manatwork's ответдля фактической причины 1h;1!H
, но я хотел бы добавить примечание о переносимости.
Стандартный и переносимый синтаксис должен быть следующим:
sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\
blub/p;}'
В противном случае это не будет работать в большинстве sed
реализаций, например, в традиционных реализациях Unix.
Это \n
понятно с левой стороны команды s
, но вам нужно использовать символ обратной косой черты, за которым следует фактический символ новой строки с правой стороны. Вам также нужно между ;
командой s
и }
, и не должно быть пробела перед p
.
Вы также можете сохранить содержимое файла в пространстве шаблонов вместо пространства удержания:
sed -n '
:1
$!{
N;b1
}
s/foo\nbar/blah\
blup/p'
Но как с шаблоном, так и с пространством хранения, большинство sed
реализаций будут работать только с небольшими файлами, поскольку большинство реализаций, отличных от GNU, имеют ограниченный размер для них (а POSIX требует, чтобы они могли хранить только 8 КБ данных).
Для переноса лучше использовать perl
:
perl -0777 -ne 'print if s/foo\nbar/blah\nblup/'
Поскольку размер не ограничен в perl
GNU, sed
однако имейте в виду, что это может повлиять на производительность системы, поскольку может в конечном итоге занять всю системную память, если вы не установили административно ограничения на использование памяти для каждого процесса.
решение2
почему есть 1!H потому что для меня 1h перезаписывает пространство шаблона и 1!H бесполезен
Никакой перезаписи не происходит, поскольку они не выполняются на одной и той же входной строке:
1h # when input line number is 1, copy pattern space to hold space
1!H # when input line number is not 1, append pattern space to hold space
Это необходимо, поскольку согласно info sed
:
`H'
Append a newline to the contents of the hold space, and then
append the contents of the pattern space to that of the hold space.
Поэтому, если вы используете только H
для добавления всех строк, перед первой строкой будет добавлен дополнительный символ новой строки:
bash-4.2$ seq 3 | sed -n 'H; ${g; p;}'
1
2
3
bash-4.2$ seq 3 | sed -n '1h; 1!H; ${g; p;}'
1
2
3