Você pode adotar abordagens diferentes dependendo se awk
trata RS
como um único caractere (como o tradicional awk
implementações faz) ou como uma expressão regular (como gawk
ou mawk
do). Arquivos vazios também são difíceis de serem considerados, pois awk
tende a ignorá-los.
gawk
, mawk
ou outras awk
implementações em que RS
pode ser um regexp.
Nessas implementações (para mawk
, cuidado com o fato de alguns sistemas operacionais como o Debian enviarem uma versão muito antiga em vez de um o moderno mantido por @ThomasDickey ), se RS
contiver um único caractere, o separador de registro é esse caractere ou awk
entra no modo de parágrafo quando RS
está vazio ou trata RS
como uma expressão regular caso contrário.
A solução é usar uma expressão regular que possivelmente não pode ser correspondida. Alguns vêm à mente como x^
ou $x
( x
antes do início ou após o final). No entanto, alguns (particularmente com gawk
) são mais caros que outros. Até agora, descobri que ^$
é o mais eficiente. Ele só pode coincidir com uma entrada vazia, mas então não haveria nada para combinar.
Então, podemos fazer:
awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
Uma ressalva é 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 instrução ENDFILE
. Mas também precisamos redefinir $0
em uma instrução BEGINFILE, pois, caso contrário, ela 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...
implementações tradicionais awk
, POSIX awk
Nesses, RS
é apenas um caractere, eles não têm BEGINFILE
/ ENDFILE
, eles não têm a variável RT
, eles geralmente também não podem processar o caractere NUL. / p>
Você poderia pensar que usar RS='
poderia funcionar, pois, de qualquer forma, eles não podem processar entradas que contenham o byte NUL, mas não, RS='
'RS=
' em implementações tradicionais é tratado como
$'\U10FFFE'
, que é o modo de parágrafo. .
Uma solução pode ser usar um caractere com pouca probabilidade de ser encontrado na entrada como sed
. Em localidades de caractere multibyte, você pode até mesmo criar sequências de bytes que são muito improváveis de ocorrer, pois elas formam caracteres que não são atribuídos ou não caracterizam como $0
em locales UTF-8. Não é realmente infalível e você também tem problemas 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
Esse é o equivalente de gawk
:
sed '
:1
$!{
N;b1
}
...' file1
Outro problema com essa abordagem é que, se o arquivo não estava terminando em um caractere de nova linha (e não estava vazio), ainda é adicionado arbitrariamente em RT
no final (com RS
, você contornar isso usando NR
em vez de FNR
no código acima). Uma vantagem é que você tem um registro do número de linhas no arquivo em %code% / %code% .