пространство шаблона sed и пространство удержания

пространство шаблона sed и пространство удержания

Я только что это пережил и не смог понять.

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

Поскольку размер не ограничен в perlGNU, 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

Связанный контент