Estaba pasando por esto y no podía entenderlo.
sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\nblub/ p }' file.
donde el archivo cat es:
foo
foo
bar
por qué lo hay 1!H
porque para mí 1h
sobrescribe el espacio del patrón y 1!H
no sirve de nada
Pero el sed one liner parece funcionar bien.
Respuesta1
VerLa respuesta de @manatworkpor el motivo real 1h;1!H
, pero quería agregar una nota de portabilidad.
La sintaxis estándar y portátil debería ser:
sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\
blub/p;}'
De lo contrario, no funcionará en la mayoría de sed
las implementaciones, por ejemplo las tradicionales de Unix.
Esto \n
se entiende en el lado izquierdo del s
comando, pero debe usar una barra invertida seguida de un carácter de nueva línea real en el lado derecho. También necesita el espacio ;
entre el s
comando y }
y ningún espacio antes del p
.
También puede almacenar el contenido del archivo en el espacio del patrón en lugar del espacio de retención:
sed -n '
:1
$!{
N;b1
}
s/foo\nbar/blah\
blup/p'
Pero tanto con el patrón como con el espacio de retención, la mayoría de sed
las implementaciones solo funcionarán con archivos pequeños, ya que la mayoría de las implementaciones que no son GNU tienen un tamaño limitado para ellos (y POSIX solo requiere que puedan contener 8 kiB de datos).
De forma portátil, sería mejor que usaras perl
:
perl -0777 -ne 'print if s/foo\nbar/blah\nblup/'
Sin embargo , debido a que el tamaño no está limitado en perl
GNU, sed
tenga en cuenta que puede tener una incidencia en el rendimiento del sistema, ya que puede terminar usando toda la memoria del sistema si no ha establecido límites administrativos en el uso de memoria por proceso.
Respuesta2
por qué hay 1!H porque para mí 1h sobrescribe el espacio del patrón y 1!H no sirve de nada
No se produce ninguna sobrescritura ya que no se ejecutan en la misma línea de entrada:
1h # when input line number is 1, copy pattern space to hold space
1!H # when input line number is not 1, append pattern space to hold space
Esto es necesario porque según info sed
:
`H'
Append a newline to the contents of the hold space, and then
append the contents of the pattern space to that of the hold space.
Entonces, si usa solo H
para agregar todas las líneas, habrá una nueva línea adicional antes de la primera línea:
bash-4.2$ seq 3 | sed -n 'H; ${g; p;}'
1
2
3
bash-4.2$ seq 3 | sed -n '1h; 1!H; ${g; p;}'
1
2
3