Мой вопрос связан с sed
-специфическим решением, данным в этом ответе на этот вопрос обратного сопоставления . sed
/ grep
Решение , которое я не могу расшифровать это следующим:
sed '1!G;h;$!d' file
Может кто-нибудь, пожалуйста, расшифровать эту команду?
Из знаний VI (M) я знаю, что G обозначает последнюю строку файла и что в sed «bang» (!), За которым следует адрес, немного похожий на grep -v
то, чтобы сказать, что он не будет соответствовать этой строке. Но в целом приведенный выше сценарий sed выше моего понимания.
sed
рецепт является чрезвычайно неэффективным способом (O (n ^ 2/2) сложность), чтобы перевернуть строки в файле. Это было бы слишком медленно для файлов с большим количеством строк. Гораздо более эффективную альтернативу реверсирования порядка строк смотрите вtac
GNU coreutils.Ответы:
Это переворачивает файл строка за строкой.
Во-первых,
sed
имеет место для удержания и шаблонное пространство . Мы должны различать их, прежде чем сосредоточиться на этой конкретной команде.Когда
sed
читает новую строку, она загружается в пространство шаблона. Поэтому это пространство перезаписывается каждый раз, когда обрабатывается новая строка. С другой стороны, пространство удержания является постоянным на протяжении всей обработки, и значения могут храниться там для дальнейшего использования.Команде:
Есть 3 команды в этом заявлении:
1!G
,h
и$!d
1!G
означает, чтоG
команда выполняется в каждой строке, кроме первой (!
отрицает1
).G
означает добавить то, что находится в удерживающем пространстве в пространство образца.h
относится к каждой строке. Он копирует пространство шаблона в пространство удержания (и перезаписывает его).$!d
применяется к каждой строке, кроме последней ($
представляет последнюю строку,!
отрицает ее).d
это команда для удаления строки (пробел).sed
выполняетсяh
команда. Первая строка копируется в область удержания. Затем он удаляется, так как он соответствует$!
условию.sed
продолжается со второй строки.1!
(это не первая строка), и поэтому пространство удержания (которое имеет первую строку) добавляется к пространству шаблона (которое имеет вторую строку). После этого в шаблонном пространстве появляется вторая строка, за которой следует первая строка, разделенная новой строкой. Теперьh
команда применяется (как в каждой строке); все, что находится в пространстве образца, копируется в пространство удержания. Применяется третье утверждение ($!d
): строка удаляется из пространства шаблона.$
) почти весь шаг 2 выполнен, но не часть удаления (d
).sed
, при вызове без-n
, автоматически печатает пространство шаблона в конце обработки для каждой строки ввода. Таким образом, когда не удаляется, пространство шаблона печатается. Теперь он содержит все строки в обратном порядке .источник
h
команда копирует пространство шаблона в пространство удержания, которое сохраняется доsed
конца. После окончания скрипта все очищается, потому что бинарный файл вышел.sed
там только один пробел. Это как переменная, которая может содержать что-то.-n
мы должны удалить каждую строку, кроме последней. В последней строке sed добавляет все из пространства удержания в пространство шаблона. И посколькуd
команда не будет выполнена, строка печатается (теперь эта строка содержит весь файл в обратном порядке).h
команда в последней строке вроде неактивна» (с дополнительным акцентом и слегка перефразированным). Он прав; Когдаsed
обрабатывается последняя строка ввода ,G
считывается пространство удержания (для добавления его в пространство образца), а затемh
копируется пространство образца в пространство удержания, на которое никогда больше не ссылаются . Мы могли бы также сказатьsed 'G;$!h;$!d'
илиsed 'G;$!{h;d}'
. (2) Мы могли бы избежать использованияd
, говоряsed -n 'G;h;$p'
.