Comment puis-je empêcher sed d'ajouter des caractères de nouvelle ligne supplémentaires

17

J'exécute les 2 sedcommandes suivantes. Le premier ajoute des caractères de nouvelle ligne là où je les veux, le second ajoute également des caractères de nouvelle ligne là où je les veux, MAIS ajoute également un caractère supplémentaire à la fin du fichier là où il n'y en avait pas auparavant.

sed -e 's|\<LIST_G_STATEMENT>|&\
|g' ${XMLDIR}/statement_tmp_1.xml > ${XMLDIR}/statement_tmp_2.xml

sed -e 's|\</LIST_G_STATEMENT>|&\
|g' ${XMLDIR}/statement_tmp_2.xml > ${XMLDIR}/statement_tmp_3.xml

L'utilisation od -csur les 3 fichiers donne la sortie suivante.

statement_tmp_1.xml (non \nà la fin du fichier)

1314700    T   A   T   E   M   E   N   T   >   <   /   L   I   S   T   _
1314720    G   _   S   T   A   T   E   M   E   N   T   >   <   /   G   _
1314740    S   E   T   U   P   >   <   /   L   I   S   T   _   G   _   S
1314760    E   T   U   P   >   <   /   A   R   X   S   G   P   O   >
1314777

statement_tmp_2.xml (non \nà la fin du fichier)

1314700    S   T   A   T   E   M   E   N   T   >   <   /   L   I   S   T
1314720    _   G   _   S   T   A   T   E   M   E   N   T   >   <   /   G
1314740    _   S   E   T   U   P   >   <   /   L   I   S   T   _   G   _
1314760    S   E   T   U   P   >   <   /   A   R   X   S   G   P   O   >
1315000

statement_tmp_3.xml ( \nà la fin du fichier - d'où vient-il?)

1314700    S   T   A   T   E   M   E   N   T   >   <   /   L   I   S   T
1314720    _   G   _   S   T   A   T   E   M   E   N   T   >  \n   <   /
1314740    G   _   S   E   T   U   P   >   <   /   L   I   S   T   _   G
1314760    _   S   E   T   U   P   >   <   /   A   R   X   S   G   P   O
1315000    >  \n
1315002

J'utilise AIX 5.3

Fondamentalement, je veux qu'il arrête d'ajouter le supplément \nou que je trouve un moyen de le supprimer.

jonnohudski
la source
Juste une question: pourquoi utilisez-vous un saut de ligne littéral dans votre modèle de substitution alors que vous auriez pu s|...|&\n|aussi bien l' utiliser ?
Joseph R.
1
@JosephR. \ndans le côté droit n'est pas portable.
Stéphane Chazelas
@StephaneChazelas C'est bizarre. Est-ce une chose CR vs CRLF?
Joseph R.
2
Un fichier qui ne se termine pas par un caractère de nouvelle ligne n'est pas un fichier texte, donc le comportement avec les utilitaires de texte sur eux n'est pas spécifié . Utilisez perlun autre outil qui peut traiter des données binaires.
Stéphane Chazelas
4
@JosephR. Non, \<LF>c'est la manière traditionnelle et POSIX d'ajouter un caractère LF. \nremplacerait généralement un ncaractère dans tout sauf GNU sed.
Stéphane Chazelas

Réponses:

10

Vous devriez vous considérer chanceux car AIX a sedajouté ces caractères de nouvelle ligne manquants.

Un fichier non vide qui ne se termine pas par un caractère de nouvelle ligne n'est pas un fichier texte (au moins selon la définition POSIX d'un fichier texte) car un fichier texte est censé contenir des lignes et les lignes sont un (pas trop) longue) séquence de caractères terminée par un caractère de nouvelle ligne, de sorte que le comportement des utilitaires de texte comme sedcelui-ci n'est pas spécifié et dans la pratique varie d'une implémentation à l'autre.

Une sedmise en œuvre aurait rejeté ces faux caractères après la dernière ligne.

AFAIK, les xmlfichiers sont censés être des fichiers texte, donc cela signifie sedsimplement les avoir corrigés pour vous.

Si vous avez besoin que ce fichier ne se termine pas par un caractère de nouvelle ligne, vous pouvez utiliser perlou d'autres outils capables de gérer des données non textuelles.

perl -pe 's|<LIST_G_STATEMENT>|$&\n|g'
Stéphane Chazelas
la source
1
La nouvelle ligne de terminaison est utile si vous prévoyez de diriger votre sedsortie vers tout autre utilitaire Unix standard. Honnêtement, je n'ai pas remarqué sedcela depuis des années , car les substitutions de commande du shell Bourne aiment $(sed 's/bas/replac/' <<<'basement')couper furtivement la dernière ligne, s'il y en a une. Mais il y a des moments où vous n'en voulez absolument pas; par exemple , manipuler le texte du presse-papiers X avec sed. FYI, GNU sed, si disponible, n'ajoute pas de nouvelle ligne de terminaison si vous l'utilisez pavec l' -noption, comme décrit dans cette réponse SE .
TheDudeAbides
0

Voici un moyen de supprimer la nouvelle ligne finale d'un fichier en utilisant dd:

printf "" | dd  of='/path/to/file' seek=<filesize_in_bytes - 1> bs=1 count=1

Pour tester si un fichier se termine par une nouvelle ligne, vous pouvez utiliser:

tail -c 1 /path/to/file | tr -dc '\n' | wc -c

Et pour obtenir la taille du fichier en octets, utilisez:

wc -c < /path/to/file
chan
la source
0

Selon ce AIX manuel IBM - tailt -rRéverse - ce qui est plutôt cool. Tant que votre fichier est inférieur à 20 Ko, les éléments suivants devraient fonctionner:

tail -r <file | dd bs=1 skip=1 | tail -r >file.new
mikeserv
la source