1 votes

Commande awk ou sed pour remplacer un saut de ligne suivi d'un texte contenant des espaces

Une réponse à une autre question suggère sed -i 's/original/replacement/g' file.txt pour remplacer des mots spécifiques dans un fichier texte. Ma situation de départ ressemble à ceci:

        Item: PRF
        Type: File
        Item: AOX
        Type: Folder
        Item: DD4
        Type: File

Ma situation finale devrait ressembler à ceci:

        Item: PRF^Type: File
        Item: AOX^Type: Folder
        Item: DD4^Type: File

Notes : (1) L'interface Ask Ubuntu semble supprimer certains des espaces avant Item: et Type:. En réalité, il y a en fait huit espaces en tête. (2) J'ai peut-être commis une erreur en utilisant des exemples simplistes de Item. Les éléments sont en réalité des chemins d'accès partiels de Windows (manquant par exemple D:), dont certains sont assez longs. Un exemple plus précis serait Item: Folder\Some Folder\A file name.txt.

J'ai essayé cela, avec et sans guillemets doubles:

sed -i 's/\n"        Type: "/\^"Type: "/g' file.txt

Cela ne me donne pas d'erreurs, mais aussi aucun changement. J'ai également essayé ceci:

awk '/ "        Item: " / { printf "%s", $0"^" } / "        Type: " / { gsub(/^[ \t]+/,"",$0); print $0 }' source.txt

J'ai essayé cela pour vérifier que je changerais uniquement les entrées avec huit espaces vides avant "Item". Cela n'a pas fonctionné. En essayant sans espaces et sans guillemets doubles, comme dans la réponse (ci-dessous), a également échoué. En essayant avec gawk -i inplace a donné source.txt contenant zéro octet.

Mon titre spécifiait initialement sed. Une réponse proposant awk m'a alerté sur cette alternative, qui (maintenant que j'y pense) semble plus capable. Mais je ne peux pas comprendre comment le faire fonctionner.

1voto

steeldriver Points 118154

Par défaut, sed ne charge qu'une ligne à la fois dans son espace de motif. Vous pouvez utiliser la commande N pour charger une autre ligne.

En fait, votre question est une variante d'une "commande en une seule ligne" bien connue pour joindre des lignes en fonction du ou des caractères initiaux de la ligne suivante1:

40. Ajouter une ligne à la précédente si elle commence par un signe égal "=".

sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

Donc, étant donné

$ cat file.txt
    Item: PRF
    Type: File
    Item: AOX
    Type: Folder
    Item: DD4
    Type: File

(qui a 4 espaces initiaux), alors

$ sed -E -e :a -e '$!N;s/\n {4}Type: (File|Folder)/^Type: \1/; ta' -e 'P;D' file.txt
    Item: PRF^Type: File
    Item: AOX^Type: Folder
    Item: DD4^Type: File

Ajoutez -i ou -i.bak pour éditer le fichier sur place une fois que vous êtes sûr qu'il fait ce qu'il faut.


Alternativement, vous pourriez utiliser le script d'édition non traçable ed suivant pour correspondre aux lignes Type:, substituer ^ pour les espaces initiaux, puis joindre à la ligne précédente, écrivant le résultat dans le même fichier:

g/^ \{4\}Type:/s//^Type:/\
-1,.j
wq

Vous pouvez implémenter cela en tant que commande shell non interactive en une seule ligne:

printf '%s\n' 'g/^ \{4\}Type:/s//^Type:/\' '-1,.j' 'wq' | ed -s file.txt

Voir Le manuel de l'éditeur de ligne GNU ed pour plus de détails.


  1. voir par exemple Explication des commandes en une ligne Sed, Partie I: Espacement de fichier, numérotation et conversion de texte et substitution

1voto

Raffa Points 11919

Je vais utiliser awk ... C'est une commande en une seule ligne simple comme suit :

awk '/Item:/ { printf "%s", $0"^" } /Type:/ { gsub(/^[ \t]+/,"",$0); print $0 }' file

C'est ... Si la ligne contient Item:, alors l'afficher sans ajouter de saut de ligne (printf n'ajoute pas de saut de ligne par défaut), mais ajoute le caractère ^ à la fin ... et si la ligne contient Type:, alors supprimer tous les espaces en début de ligne et l'afficher en ajoutant un saut de ligne (print ajoute un saut de ligne par défaut).

La commande ci-dessus ne modifiera pas le fichier d'origine mais affichera le texte modifié dans le terminal.

Pour éditer le fichier d'origine directement, utilisez l'option -i inplace de GNU awk (Peut être la valeur par défaut sur Ubuntu ... Vérifiez avec awk -W version) ou sinon, vous pouvez installer gawk puis l'utiliser comme suit :

gawk -i inplace '/Item:/ { printf "%s", $0"^" } /Type:/ { gsub(/^[ \t]+/,"",$0); print $0 }' file

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X