Você pode adotar diferentes abordagens, dependendo se awk
trata RS
como um único caractere (como as awk
implementações tradicionais fazem) ou como uma expressão regular (como gawk
ou mawk
faz). Arquivos vazios também são difíceis de serem considerados, pois awk
tendem a ignorá-los.
gawk
, mawk
ou outras awk
implementações em que RS
pode ser uma regexp.
Nessas implementações (por favor mawk
, cuidado com o fato de que alguns sistemas operacionais, como o Debian, enviam uma versão muito antiga em vez da moderna mantida por @ThomasDickey ), se RS
contiver um único caractere, o separador de registros é esse caractere ou awk
entra no modo de parágrafo quando RS
está vazio, ou trata RS
como uma expressão regular de outra forma.
A solução é usar uma expressão regular que não possa ser correspondida. Alguns vêm à mente como x^
ou $x
( x
antes do início ou depois do fim). No entanto, alguns (particularmente com gawk
) são mais caros que outros. Até agora, descobri que ^$
é o mais eficiente. Ele pode corresponder apenas a uma entrada vazia, mas não haveria nada contra o que corresponder.
Para que possamos fazer:
awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
Uma ressalva, porém, é que ele pula arquivos vazios (ao contrário de perl -0777 -n
). Isso pode ser resolvido com o GNU awk
, colocando o código em uma ENDFILE
declaração. Mas também precisamos redefinir $0
em uma instrução BEGINFILE, pois, caso contrário, não seria redefinida após o processamento de um arquivo vazio:
gawk -v RS='^$' '
BEGINFILE{$0 = ""}
ENDFILE{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
awk
implementações tradicionais , POSIXawk
Nesses, RS
é apenas um caractere, eles não têm BEGINFILE
/ ENDFILE
, eles não têm a RT
variável, geralmente também não podem processar o caractere NUL.
Você pensaria que o uso RS='\0'
poderia funcionar, pois, de qualquer maneira, eles não podem processar a entrada que contém o byte NUL, mas não, que RS='\0'
nas implementações tradicionais é tratado como RS=
, que é o modo de parágrafo.
Uma solução pode ser usar um caractere improvável de ser encontrado na entrada como \1
. Nos códigos de idioma de caracteres com vários bytes, é possível fazer com que seja muito improvável que sequências de bytes ocorram, pois formam caracteres que não são atribuídos ou não como caracteres $'\U10FFFE'
nos códigos de idioma UTF-8. Não é realmente infalível e você também tem um problema com arquivos vazios.
Outra solução pode ser armazenar toda a entrada em uma variável e processá-la na instrução END no final. Isso significa que você pode processar apenas um arquivo por vez:
awk '{content = content $0 RS}
END{$0 = content
printf "%s: <%s>\n", FILENAME, $0
}' file
Isso é o equivalente a sed
's:
sed '
:1
$!{
N;b1
}
...' file1
Outro problema com essa abordagem é que, se o arquivo não estava terminando com um caractere de nova linha (e não estava vazio), um ainda é adicionado arbitrariamente $0
no final (com gawk
, você contornaria isso usando em RT
vez de RS
no código acima). Uma vantagem é que você possui um registro do número de linhas no arquivo em NR
/ FNR
.