¿Cuál es el significado de: a; $! N; en un comando sed?

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

El sedcomando anterior reemplaza el nuevo carácter de línea con la cadena "cadena". Pero no sé el significado de :a;$!N;s/\n/string/;tadentro de las comillas simples. Conozco la parte del medio s/\n/string/. Pero no sé la función de la primera ( :a;$!N;) y última ( ta) parte.

Avinash Raj
fuente
¿Qué hay de la última parte?
Avinash Raj
El comando "t" se ramifica a una etiqueta con nombre si el último comando sustituto modificó el espacio del patrón.
xiaodongjie

Respuestas:

17

Estos son los sedcomandos , ciertamente crípticos . Específicamente (de man sed):

: etiqueta
         Etiqueta para los comandos byt.

t etiqueta
         Si como /// ha realizado una sustitución exitosa desde que se leyó la última línea de entrada y desde el último comando t o T, bifurque a etiqueta; Si se omite la etiqueta, bifurca hasta el final del guión.

n N Lee / agrega la siguiente línea de entrada en el espacio del patrón.

Por lo tanto, el script que publicó puede desglosarse en (espacios agregados para facilitar la lectura):

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`.

Básicamente, lo que está haciendo podría escribirse en pseudocódigo como

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

Puede entender esto un poco mejor con un ejemplo de entrada más complejo:

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

No estoy realmente seguro de por qué !$se necesita. Por lo que puedo decir, puedes obtener la misma salida con

printf "line1\nline2\nline3\nline4\nline5\n" | sed ':a;N;s/\n/string/;ta'
terdon
fuente
1
El! $ Es no coincidir con la última línea nueva, IMO.
Braiam
@Braiam no muy seguro de eso, es $!no !$. Sin embargo, también podría ser !Ny no $!.
terdon
Yo estaba tratando de analizar la página textinfo pero no encontré referencias a ninguno !No $!. Entonces, sigo pensando que está buscando si la última línea es nueva línea o EOF.
Braiam
44
Trato de pensar en $!como una dirección 'rango' con un operador de sufijo complemento - así $!N(hacer Ntodas partes excepto por la dirección $) es realmente la misma sintaxis que algo así como m,n!d(borrar todo excepto las líneas ma n).
Steeldriver 05 de
:es análogo a la gotoetiqueta, y de hecho :solía ir a la etiqueta en el caparazón de Thompson, por lo que sería familiar para las personas que usaban tanto el caparazón de sed como el de Thompson
Sergiy Kolodyazhnyy
0

He puesto esta respuesta ya que veo una gran confusión acerca de por qué la última línea se excluye al ejecutar N(a través de la cadena frente a la línea $!), y porque el PO estaba confundido sobre el significado de :a;$!N; en un comando sed , no sólo en el concreto uno que publicó .

Bueno, el beneficio de usar en $!Nlugar de Nno es evidente en los ejemplos propuestos (por el OP y por @terdon), ya que no se ejecuta un comando "importante" (seguir leyendo) en la última línea después del Ncomando. (De hecho, el resultado es el mismo si se quita esa dirección de línea).

En un ejemplo más complejo (por ejemplo, sustituir this sentenceen un archivo, con las dos palabras que aparecen a veces en una línea y otras veces en dos líneas), ¡excluir la última línea para el Ncomando podría ser crucial! Si no se excluye la última línea, al ejecutarla N, sedgolpea EOFy sale inmediatamente, evitando que se ejecuten todos los comandos posteriores (también comandos de ramificación, a saber, ty b).

En los ejemplos demasiado simplistas que se muestran, podemos eliminar de forma segura $!y dejar que sedfalle en la ejecución Ny regresar ya que el scomando abortado no haría nada si se ejecutara, ya que no hay \ncoincidencias.

Enrico Maria De Angelis
fuente