Меня смущают две концепции в sed: пространство для хранения и пространство шаблонов. Может кто-нибудь помочь им объяснить?
Вот отрывок из руководства:
h H Copy/append pattern space to hold space. g G Copy/append hold space to pattern space. n N Read/append the next line of input into the pattern space.
Эти шесть команд меня действительно сбивают с толку.
echo $'1\n2\n3\n4' | sed -n '1~2h;2~2{p;x;p}'
info sed
. Он гораздо более подробный, чем простая справочная страница.Ответы:
Когда СЭД читает файл построчно, линия , которая была в настоящее время чтения вставляется в шаблон буфера (модель пространства). Буфер шаблонов похож на временный буфер, блокнот, в котором хранится текущая информация. Когда вы приказываете sed печатать, он печатает буфер шаблонов.
Буфер удержания / пространство удержания похоже на долгосрочное хранилище, так что вы можете что-то поймать, сохранить и повторно использовать позже, когда sed обрабатывает другую строку. Вы не обрабатываете пространство удержания напрямую, вместо этого вам нужно скопировать его или добавить в пространство шаблона, если вы хотите что-то с ним сделать. Например, команда печати
p
печатает только пространство шаблона. Точно так жеs
работает с пространством шаблонов.Вот пример:
(опция -n подавляет автоматическую печать строк)
Есть три команды здесь:
1!G
,h
и$p
.1!G
имеет адрес1
(первая строка), но это!
означает, что команда будет выполняться везде, кроме первой строки.$p
с другой стороны, будет выполняться только в последней строке. Так вот что происходит:h
копирует первую строку в удерживаемое пространство.G
, добавляя содержимое буфера удержания к буферу шаблона, разделяя его новой строкой. Пространство шаблонов теперь содержит вторую строку, новую строку и первую строку.h
команда вставляет объединенное содержимое буфера шаблона в область удержания, которая теперь содержит перевернутые строки две и одну.Наконец, после того, как последняя строка была прочитана и пространство удержания (содержащее все предыдущие строки в обратном порядке) было добавлено к пространству образца, пространство образца печатается с
p
. Как вы уже догадались, приведенное выше делает именно то, чтоtac
делает команда - печатает файл в обратном порядке.источник
'195,210{/add/p}'
… Можно ли извлечь последнюю строку из группы строк, входящих в паттерн?@ Эд Мортон: Я с вами не согласен. Я нашел
sed
очень полезным и простым (как только вы разберетесь с концепцией шаблона и буферов хранения) придумать элегантный способ выполнения многострочного поиска.Например, возьмем текстовый файл с именами хостов и некоторой информацией о каждом хосте с большим количеством мусора между ними, который меня не волнует.
Для меня сценарий awk, который просто получает строки с именем хоста и соответствующей
info
строкой, занимает немного больше, чем то, что я могу сделать с помощью sed:вывод выглядит так:
(Обратите внимание, что
Host: foo1
на выходе появляется дважды.)Пояснение:
-n
отключает вывод, если явно не напечатанHost:
строку в буфер удержания (h)Host:
строку, затем повторно меняет (x) и печатает (p) строку Info :.Да, это упрощенный пример, но я подозреваю, что это обычная проблема, с которой быстро справился простой однострочник sed. Для гораздо более сложных задач, таких как те, в которых вы не можете полагаться на заданную предсказуемую последовательность, awk может лучше подойти.
источник
grep 'Host\|Info'
awk
эквивалент вашего кода sed тоже довольно короткий:awk '/Host:/{hold=$0}; /Info/{print hold; print;}' myfile.txt
Несмотря на то, что ответ @ January и пример хороши, объяснения мне было недостаточно. Мне пришлось много искать и узнавать, пока я не смог понять, как именно
sed -n '1!G;h;$p'
работает. Поэтому я хотел бы подробнее рассказать о команде для кого-то вроде меня.Прежде всего, давайте посмотрим, что делает команда.
Он меняет ввод, как это
tac
делает команда.sed
читает построчно, поэтому давайте посмотрим, что происходит в пространстве шаблона и в пространстве удержания в каждой строке. Посколькуh
команда копирует содержимое пространства шаблона в пространство удержания, оба пространства имеют одинаковый текст.В последней строке
$p
печатаетсяd\nc\nb\na$
формат,Если вы хотите видеть пространство образца для каждой строки, вы можете добавить
l
команду.Мне было очень полезно посмотреть этот видеоурок Понимание того , как работает sed , поскольку парень шаг за шагом показывает, как каждое пространство будет использоваться. Об интервале удержания упоминается в 4-м уроке, но я рекомендую посмотреть все видео, если вы не знакомы с ними
sed
.Также очень хорошими ссылками являются документ GNU sed и учебник Брюса Барнетта по Sed .
источник