Puede adoptar diferentes enfoques dependiendo de si se awktrata RScomo un solo carácter (como lo hacen las awkimplementaciones tradicionales ) o como una expresión regular (como gawko mawkhacer). Los archivos vacíos también son difíciles de considerar, ya que awktienden a omitirlos.
gawk, mawkU otras awkimplementaciones en las que RSpueden 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 RScontiene un solo carácter, el separador de registros es ese carácter o awkingresa al modo de párrafo cuando RSestá vacío, o trata RScomo 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( xantes 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 awkcolocando el código en una ENDFILEdeclaración. Pero también necesitamos restablecer $0en 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...
awkimplementaciones tradicionales , POSIXawk
En esos, RSsolo hay un personaje, no tienen BEGINFILE/ ENDFILE, no tienen la RTvariable, 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 $0al final (con gawk, evitaría eso al usarlo en RTlugar de RSen 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 ...)awkno hace la división si no lo hacemos. Dicho esto, ni siquiera el/bin/awkSolaris 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?).