Puede adoptar diferentes enfoques dependiendo de si se awk
trata RS
como un solo carácter (como lo hacen las awk
implementaciones tradicionales ) o como una expresión regular (como gawk
o mawk
hacer). Los archivos vacíos también son difíciles de considerar, ya que awk
tienden a omitirlos.
gawk
, mawk
U otras awk
implementaciones en las que RS
pueden ser una expresión regular.
En esas implementaciones (para mawk
, tenga en cuenta que algunos sistemas operativos como Debian envían una versión muy antigua en lugar de la moderna mantenida por @ThomasDickey ), si RS
contiene un solo carácter, el separador de registros es ese carácter o awk
ingresa al modo de párrafo cuando RS
está vacío, o trata RS
como una expresión regular de lo contrario.
La solución es usar una expresión regular que no se pueda igualar. Algunos vienen a la mente como x^
o $x
( x
antes del comienzo o después del final). Sin embargo, algunos (particularmente con gawk
) son más caros que otros. Hasta ahora, he encontrado que ^$
es el más eficiente. Solo puede coincidir con una entrada vacía, pero entonces no habría nada contra lo que comparar.
Entonces podemos hacer:
awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
Sin embargo, una advertencia es que omite archivos vacíos (al contrario de perl -0777 -n
). Eso se puede abordar con GNU awk
colocando el código en una ENDFILE
declaración. Pero también necesitamos restablecer $0
en una declaración BEGINFILE, ya que de lo contrario no se restablecería después de procesar un archivo vacío:
gawk -v RS='^$' '
BEGINFILE{$0 = ""}
ENDFILE{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
awk
implementaciones tradicionales , POSIXawk
En esos, RS
solo hay un personaje, no tienen BEGINFILE
/ ENDFILE
, no tienen la RT
variable, generalmente tampoco pueden procesar el carácter NUL.
Pensaría que usar RS='\0'
podría funcionar entonces, ya que de todos modos no pueden procesar la entrada que contiene el byte NUL, pero no, RS='\0'
en las implementaciones tradicionales se trata como RS=
, que es el modo de párrafo.
Una solución puede ser usar un carácter que es poco probable que se encuentre en la entrada como \1
. En las configuraciones regionales de caracteres multibyte, incluso puede crear secuencias de bytes que es muy poco probable que ocurran ya que forman caracteres que no están asignados o que no son caracteres como $'\U10FFFE'
en las configuraciones regionales UTF-8. Sin embargo, no es realmente infalible y también tiene un problema con los archivos vacíos.
Otra solución puede ser almacenar toda la entrada en una variable y procesarla en la instrucción END al final. Sin embargo, eso significa que solo puede procesar un archivo a la vez:
awk '{content = content $0 RS}
END{$0 = content
printf "%s: <%s>\n", FILENAME, $0
}' file
Eso es el equivalente de sed
's:
sed '
:1
$!{
N;b1
}
...' file1
Otro problema con ese enfoque es que si el archivo no terminaba en un carácter de nueva línea (y no estaba vacío), uno todavía se agrega arbitrariamente $0
al final (con gawk
, evitaría eso al usarlo en RT
lugar de RS
en el código de arriba). Una ventaja es que tiene un registro del número de líneas en el archivo en NR
/ FNR
.
tr '\n' 'thatchar'
el archivo antes de enviarlo a awk ytr 'thatchar' \n'
la salida. (es posible que deba agregar una nueva línea para asegurarse, como señalé anteriormente, que su archivo de entrada tiene una nueva línea final:{ tr '\n' 'missingchar' < thefile ; printf "\n" ;} | awk ..... | { tr 'missingchar' '\n' }
(pero eso agrega un '\ n' al final, de lo que tal vez deba deshacerse de ... tal vez agregar un sed antes del último tr? si ese tr acepta archivos sin terminar las nuevas líneas ...)awk
no hace la división si no lo hacemos. Dicho esto, ni siquiera el/bin/awk
Solaris 9 (basado en el awk de 1970) tenía esa limitación, por lo que no estoy seguro de que podamos encontrar uno que sí lo tenga (aún posible, ya que el roble de SVR4 tenía un límite de 99 y nawk 199, por lo que es probablemente el aumento de ese límite fue agregado por Sun y no se puede encontrar en otros awks basados en SVR4, ¿puede probar en AIX?).