Vous pouvez prendre différentes approches selon que awk
traite RS
comme un seul caractère (comme traditionnelles awk
mises en œuvre font) ou comme une expression régulière (comme gawk
ou mawk
faire). Les fichiers vides sont également difficiles à considérer car ils ont awk
tendance à les ignorer.
gawk
, mawk
ou d'autres awk
implémentations où RS
peut être une expression rationnelle.
Dans ces implémentations ( mawk
sachez que certains systèmes d'exploitation comme Debian livrent une version très ancienne au lieu de la version moderne maintenue par @ThomasDickey ), s'il RS
contient un seul caractère, le séparateur d'enregistrement est ce caractère, ou awk
passe en mode paragraphe lorsqu'il RS
est vide, ou traite RS
comme une expression régulière dans le cas contraire.
La solution consiste à utiliser une expression régulière qui ne peut pas correspondre. Certains viennent à l'esprit comme x^
ou $x
( x
avant le début ou après la fin). Cependant, certains (en particulier avec gawk
) sont plus chers que d'autres. Jusqu'à présent, j'ai trouvé que ^$
c'était le plus efficace. Il ne peut correspondre qu'à une entrée vide, mais il n'y aurait alors rien à comparer.
On peut donc faire:
awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
Une mise en garde est cependant qu'il saute les fichiers vides (contrairement à perl -0777 -n
). Cela peut être résolu avec GNU awk
en mettant le code dans une ENDFILE
instruction à la place. Mais nous devons également réinitialiser $0
dans une instruction BEGINFILE car elle ne serait pas autrement réinitialisée après le traitement d'un fichier vide:
gawk -v RS='^$' '
BEGINFILE{$0 = ""}
ENDFILE{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
awk
implémentations traditionnelles , POSIXawk
Dans ceux-ci, il RS
n'y a qu'un seul caractère, ils n'ont pas BEGINFILE
/ ENDFILE
, ils n'ont pas la RT
variable, ils ne peuvent généralement pas non plus traiter le caractère NUL.
On pourrait penser que l'utilisation RS='\0'
pourrait fonctionner alors car de toute façon ils ne peuvent pas traiter l'entrée qui contient l'octet NUL, mais non, celle RS='\0'
dans les implémentations traditionnelles est traitée comme RS=
, qui est le mode paragraphe.
Une solution peut être d'utiliser un caractère qui ne se trouvera probablement pas dans l'entrée comme \1
. Dans les paramètres régionaux de caractères multi-octets, vous pouvez même créer des séquences d'octets qui sont très peu susceptibles de se produire car ils forment des caractères qui ne sont pas affectés ou des caractères non comme $'\U10FFFE'
dans les paramètres régionaux UTF-8. Pas vraiment infaillible et vous avez également un problème avec les fichiers vides.
Une autre solution peut être de stocker l'intégralité de l'entrée dans une variable et de la traiter dans l'instruction END à la fin. Cela signifie que vous ne pouvez traiter qu'un seul fichier à la fois:
awk '{content = content $0 RS}
END{$0 = content
printf "%s: <%s>\n", FILENAME, $0
}' file
C'est l'équivalent de sed
:
sed '
:1
$!{
N;b1
}
...' file1
Un autre problème avec cette approche est que si le fichier ne se terminait pas par un caractère de nouvelle ligne (et n'était pas vide), un est toujours ajouté arbitrairement $0
à la fin (avec gawk
, vous contourneriez cela en utilisant RT
au lieu de RS
dans le code ci-dessus). Un avantage est que vous avez un enregistrement du nombre de lignes dans le fichier dans NR
/ FNR
.
tr '\n' 'thatchar'
le fichier avant de l'envoyer à awk, ettr 'thatchar' \n'
la sortie? (vous devrez peut-être encore ajouter une nouvelle ligne pour vous assurer, comme je l'ai noté ci-dessus, que votre fichier d'entrée a une nouvelle ligne de fin:{ tr '\n' 'missingchar' < thefile ; printf "\n" ;} | awk ..... | { tr 'missingchar' '\n' }
(mais qui ajoute un '\ n' à la fin, dont vous devrez peut-être vous débarrasser ... peut-être ajout d'un sed avant le tr final si ce tr accepte des fichiers sans terminer les sauts de ligne ...)awk
ne fait pas le fractionnement si nous ne le faisons pas. Cela dit, même le/bin/awk
Solaris 9 (basé sur le awk des années 1970) n'avait pas cette limitation, donc je ne suis pas sûr que nous puissions en trouver un qui le fait (toujours possible car l'oawk du SVR4 avait une limite de 99 et nawk 199, donc c'est la levée de cette limite a probablement été ajoutée par Sun et peut ne pas être trouvée dans d'autres awks basés sur SVR4, pouvez-vous tester sur AIX?).