Яке значення: a; $! N; в команді sed?


11
$ (echo hello; echo there) | sed ':a;$!N;s/\n/string/;ta'
hellostringthere

Вищенаведена sedкоманда замінює символ нового рядка рядком "рядок". Але я не знаю сенсу в :a;$!N;s/\n/string/;taрамках однієї цитати. Я знаю середню частину s/\n/string/. Але я не знаю функції першої ( :a;$!N;) та останньої ( ta) частини.


2
будь ласка , дивіться на stackoverflow.com/questions/1251999 / ... .
xiaodongjie

Що з останньою частиною?
Авінаш Радж

Команда "t" відгалужується до названої мітки, якщо остання команда-заміна змінила простір шаблону.
xiaodongjie

Відповіді:


17

Це, звичайно ж, загадкові sedкоманди. Конкретно (від man sed):

: мітка
         Мітка для команд b і t.

t label
         Якщо /// зробила успішну заміну після прочитання останнього рядка введення та з останньої команди t або T, то гілка на мітку; якщо мітка пропущена, відгалуження до кінця скрипту.

n N Читання / додавання наступного рядка вводу в простір шаблону.

Отже, сценарій, який ви опублікували, можна розбити на (пробіли, додані для читання):

sed ':a;  $!N;  s/\n/string/;  ta'
     ---  ----  -------------  --
      |     |        |          |--> go back (`t`) to `a`
      |     |        |-------------> substitute newlines with `string`
      |     |----------------------> If this is not the last line (`$!`), append the 
      |                              next line to the pattern space.
      |----------------------------> Create the label `a`.

В основному, те, що це робиться, може бути записано в псевдокоді як

while (not end of line){
    append current line to this one and replace \n with 'string'
}

Ви можете це зрозуміти трохи краще на прикладі більш складного вводу:

$ printf "line1\nline2\nline3\nline4\nline5\n" | sed ':a;$!N;s/\n/string/;ta'
line1stringline2stringline3stringline4stringline5

Я не дуже впевнений, навіщо !$це потрібно. Наскільки я можу сказати, ви можете отримати той самий вихід

printf "line1\nline2\nline3\nline4\nline5\n" | sed ':a;N;s/\n/string/;ta'

1
$! Не відповідає останнім новим рядком, IMO.
Брайам

@Braiam не надто впевнений у цьому, це $!не так !$. Однак це може бути !Nі ні $!.
тердон

Я намагався розібрати сторінку TeXinfo - але не знайшов посилання на ні !Nабо $!. Отже, я все ще продовжую міркувати, що шукає, чи є останній рядок новим рядком або EOF.
Брайам

4
Я намагаюся розглядати $!як адресу 'діапазон' з оператором доповнення до постфікса - так що $!N(робити Nвсюди, крім адреси $), це дійсно той самий синтаксис, як щось подібне m,n!d(видалити все, крім рядків mдо n).
steeldriver

:є аналогом gotoетикетки, а насправді :це був goto label в оболонці Томпсона, тому люди були відомі ще в той день, використовуючи як sed, так і оболонку Thompson
Сергій Колодяжний

0

Я відправляю цей відповідь , так як я бачу багато плутанини щодо чому останній рядок виключається при виконанні N(через адресації рядки рядки $!) і тому , що ОП був збентежений про значення :a;$!N; в вигляді SED команди , а не тільки в до однієї конкретної він відповідав .

Ну а користь використання $!Nзамість Nне є вигідною у запропонованих прикладах (ОП та @terdon), оскільки жодна важлива команда (тримати читання) не виконується в останньому рядку після Nкоманди. (Дійсно, результат такий самий, якщо викреслити адресу рядка.)

У більш складному прикладі (наприклад, підміна this sentenceу файлі, коли два слова іноді з’являються в одному рядку, а інший раз у двох рядках), виключаючи останній рядок для Nкоманди, може бути вирішальним! Якщо останній рядок не виключається, після його виконання N, sedнатискає на EOFта негайно виходить з нього, не дозволяючи виконувати всі наступні команди (а також команди розгалуження, а саме tі b).

У наведених занадто спрощених прикладах ми можемо безпечно видалити $!і sedне допустити провалу у виконанні Nта поверненні, оскільки перервана sкоманда нічого не зробила б, якщо вона була виконана, оскільки немає \nвідповідності.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.