90 votes

Le '+' (une ou plusieurs occurrences) ne fonctionne pas avec la commande 'sed'.

J'essaie d'affiner mon code en me débarrassant des espaces blancs inutiles, des lignes vides et en équilibrant les parenthèses avec un espace entre elles :

    int a = 4;
    if ((a==4) ||   (b==5))

    a++   ;

devrait changer en :

    int a = 4;
    if ( (a==4) || (b==5) )
    a++ ;

Cela fonctionne pour les parenthèses et les lignes vides. Cependant, il oublie de réduire les espaces multiples à un seul espace :

    int a = 4;
    if ( (a==4) ||   (b==5) )
    a++    ;

Voici mon script :

    #!/bin/bash
    # Script to refine code
    #
    filename=read.txt

    sed 's/((/( (/g' $filename > new.txt
    mv new.txt $filename

    sed 's/))/) )/g' $filename > new.txt
    mv new.txt $filename

    sed 's/ +/ /g' $filename > new.txt
    mv new.txt $filename

    sed '/^$/d' $filename > new.txt
    mv new.txt $filename

Par ailleurs, existe-t-il un moyen de rendre ce script plus concis, par exemple en supprimant ou en réduisant le nombre de commandes ?

97voto

Sicco Points 3053

Si vous utilisez GNU sed alors vous devez utiliser sed -r qui oblige sed d'utiliser des expressions régulières étendues, y compris le comportement souhaité des + . Voir man sed :

-r, --regexp-extended

       use extended regular expressions in the script.

Il en va de même si vous utilisez OS X sed mais vous devez alors utiliser sed -E :

-E      Interpret regular expressions as extended (modern) regular expressions
        rather than basic regular regular expressions (BRE's).

21voto

choroba Points 56333

Vous devez précéder + avec un \ sinon sed essaie de faire correspondre le caractère + lui-même.

Pour rendre le script plus "intelligent", vous pouvez accumuler toutes les expressions dans un seul sed :

sed -e 's/((/( (/g' -e 's/))/) )/g' -e 's/ \+/ /g' -e '/^$/d' $filename > new.txt

Certaines implémentations de sed même soutenir le -i qui permet de modifier le fichier en place .

14voto

bluebaby Points 131

Parfois, -r et -e ne fonctionnent pas. J'utilise la version 4.2.1 de sed et ils ne fonctionnent pas du tout pour moi.

Une astuce rapide consiste à utiliser l'opérateur * à la place. Disons que nous voulons remplacer tous les caractères d'espace redondants par un seul espace : Nous aimerions le faire :

sed 's/ +/ /'

Mais nous pouvons utiliser ceci à la place :

sed 's/  */ /'

(notez le double espace)

4voto

dosentmatter Points 138

Ce n'est peut-être pas la solution la plus propre. Mais si vous voulez éviter -E y -r pour rester compatible avec les deux versions de sed, vous pouvez faire un caractère de répétition cc* - c'est 1 c puis 0 ou plus c 's == 1 ou plus c 's.

Ou utilisez simplement la syntaxe BRE, comme suggéré par @cdarke pour correspondre à un nombre spécifique ou à des motifs c\{1,\} . Le deuxième chiffre après la virgule est exclu pour signifier 1 ou plus.

1voto

potong Points 18653

Cela pourrait marcher pour vous :

sed -e '/^$/d' -e ':a' -e 's/\([()]\)\1/\1 \1/g' -e 'ta' -e 's/  */ /g' $filename >new.txt

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X