Estoy confundido por los dos conceptos en sed: mantener el espacio y el espacio del patrón. ¿Alguien puede ayudar a explicarlos?
Aquí hay un fragmento del manual:
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.
Estos seis comandos realmente me confunden.
echo $'1\n2\n3\n4' | sed -n '1~2h;2~2{p;x;p}'
info sed
. Es mucho más detallado que la simple página de manual.Respuestas:
Cuando sed lea un archivo línea por línea, la línea que se ha leído actualmente se inserta en el modelo de memoria intermedia (espacio de patrones). El búfer de patrones es como el búfer temporal, el bloc de notas donde se almacena la información actual. Cuando le dice a sed que imprima, imprime el búfer de patrón.
Mantener búfer / espacio de espera es como un almacenamiento a largo plazo, de modo que puede capturar algo, almacenarlo y reutilizarlo más tarde cuando sed esté procesando otra línea. No procesa directamente el espacio de reserva, en su lugar, debe copiarlo o agregarlo al espacio del patrón si desea hacer algo con él. Por ejemplo, el comando de impresión
p
imprime solo el espacio del patrón. Asimismo,s
opera sobre el espacio del patrón.Aquí hay un ejemplo:
(la opción -n suprime la impresión automática de líneas)
Hay tres comandos aquí:
1!G
,h
y$p
.1!G
tiene una dirección,1
(primera línea), pero!
significa que el comando se ejecutará en todas partes menos en la primera línea.$p
por otro lado, solo se ejecutará en la última línea. Entonces, lo que pasa es esto:h
copia la primera línea en el espacio de espera .G
, agregando el contenido del búfer de retención al búfer de patrón, separándolo por una nueva línea. El espacio del patrón ahora contiene la segunda línea, una nueva línea y la primera línea.h
comando inserta el contenido concatenado del búfer de patrón en el espacio de espera, que ahora contiene las líneas invertidas dos y uno.Finalmente, después de que se haya leído la última línea y se haya agregado el espacio de espera (que contiene todas las líneas anteriores en orden inverso) al espacio del patrón, el espacio del patrón se imprime con
p
. Como habrá adivinado, lo anterior hace exactamente lo que hace eltac
comando: imprime el archivo al revés.fuente
'195,210{/add/p}'
… ¿Es posible extraer la última línea de un grupo de líneas involucradas en un patrón?@Ed Morton: No estoy de acuerdo contigo aquí. Encontré
sed
muy útil y simple (una vez que asimilas el concepto del patrón y mantienes los búferes) para encontrar una forma elegante de hacer grepping multilínea.Por ejemplo, tomemos un archivo de texto que tiene nombres de host y algo de información sobre cada host, con mucha basura en el medio que no me importa.
Para mí, un script awk para obtener las líneas con el nombre de host y la
info
línea correspondiente tomaría un poco más de lo que puedo hacer con sed:la salida se ve así:
(Tenga en cuenta que
Host: foo1
aparece dos veces en la salida).Explicación:
-n
desactiva la salida a menos que se imprima explícitamenteHost:
línea en el búfer de retención (h)Host:
línea, luego vuelve a intercambiar (x) e imprime (p) la línea Info :.Sí, este es un ejemplo simplista, pero sospecho que este es un problema común que se solucionó rápidamente con un simple sed one-liner. Para tareas mucho más complejas, como aquellas en las que no puede confiar en una secuencia predecible y dada, awk puede ser más adecuado.
fuente
grep 'Host\|Info'
awk
equivalente de su código sed también es bastante corto:awk '/Host:/{hold=$0}; /Info/{print hold; print;}' myfile.txt
Aunque la respuesta de @ January y el ejemplo son agradables, la explicación no fue suficiente para mí. Tuve que buscar y aprender mucho hasta que logré entender cómo
sed -n '1!G;h;$p'
funciona exactamente . Así que me gustaría dar más detalles sobre el comando para alguien como yo.En primer lugar, veamos qué hace el comando.
Invierte la entrada como lo
tac
hace el comando.sed
lee línea por línea, así que veamos qué sucede en el espacio de patrón y el espacio de espera en cada línea. Como elh
comando copia el contenido del espacio del patrón en el espacio de espera, ambos espacios tienen el mismo texto.En la última línea, se
$p
imprime cond\nc\nb\na$
el formatoSi desea ver el espacio del patrón para cada línea, puede agregar un
l
comando.Me resultó muy útil ver este video tutorial Comprender cómo funciona sed , ya que el chico muestra cómo se usará cada espacio paso a paso. La retención espaciada se hace referencia en el cuarto tutorial, pero recomiendo ver todos los videos si no está familiarizado
sed
.También el documento sed de GNU y el tutorial Sed de Bruce Barnett son muy buenas referencias.
fuente