Unix / Linux - Expressions régulières avec SED

Dans ce chapitre, nous discuterons en détail des expressions régulières avec SED sous Unix.

Une expression régulière est une chaîne qui peut être utilisée pour décrire plusieurs séquences de caractères. Les expressions régulières sont utilisées par plusieurs commandes Unix différentes, notammented, sed, awk, grep, et dans une mesure plus limitée, vi.

Ici SED signifie stream editor. Cet éditeur orienté flux a été créé exclusivement pour l'exécution de scripts. Ainsi, toute l'entrée que vous y introduisez passe et va vers STDOUT et cela ne change pas le fichier d'entrée.

Invoquer sed

Avant de commencer, assurons-nous d'avoir une copie locale de /etc/passwd fichier texte avec lequel travailler sed.

Comme mentionné précédemment, sed peut être appelé en lui envoyant des données via un tube comme suit -

$ cat /etc/passwd | sed
Usage: sed [OPTION]... {script-other-script} [input-file]...

  -n, --quiet, --silent
                 suppress automatic printing of pattern space
  -e script, --expression = script
...............................

le cat la commande vide le contenu de /etc/passwd à sedà travers le tuyau dans l'espace de modèle de sed. L'espace de motif est le tampon de travail interne utilisé par sed pour ses opérations.

La syntaxe générale sed

Voici la syntaxe générale de sed -

/pattern/action

Ici, pattern est une expression régulière, et actionest l'une des commandes données dans le tableau suivant. Sipattern est omis, action est effectuée pour chaque ligne comme nous l'avons vu ci-dessus.

Le caractère barre oblique (/) qui entoure le motif est obligatoire car il est utilisé comme délimiteur.

Sr.No. Gamme et description
1

p

Imprime la ligne

2

d

Supprime la ligne

3

s/pattern1/pattern2/

Remplace la première occurrence de pattern1 par pattern2

Suppression de toutes les lignes avec sed

Nous allons maintenant comprendre comment supprimer toutes les lignes avec sed. Invoquez à nouveau sed; mais le sed est maintenant censé utiliser leediting command delete line, indiqué par la lettre unique d -

$ cat /etc/passwd | sed 'd'
$

Au lieu d'appeler sed en lui envoyant un fichier via un tube, le sed peut être invité à lire les données d'un fichier, comme dans l'exemple suivant.

La commande suivante fait exactement la même chose que dans l'exemple précédent, sans la commande cat -

$ sed -e 'd' /etc/passwd
$

Les adresses sed

Le sed prend également en charge les adresses. Les adresses sont soit des emplacements particuliers dans un fichier, soit une plage dans laquelle une commande d'édition particulière doit être appliquée. Lorsque le sed ne rencontre aucune adresse, il effectue ses opérations sur chaque ligne du fichier.

La commande suivante ajoute une adresse de base à la commande sed que vous avez utilisée -

$ cat /etc/passwd | sed '1d' |more
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
$

Notez que le numéro 1 est ajouté avant le delete editcommander. Cela demande au sed d'exécuter la commande d'édition sur la première ligne du fichier. Dans cet exemple, le sed supprimera la première ligne de/etc/password et imprimez le reste du fichier.

Les gammes d'adresses sed

Nous allons maintenant comprendre comment travailler avec the sed address ranges. Alors que faire si vous souhaitez supprimer plus d'une ligne d'un fichier? Vous pouvez spécifier une plage d'adresses avec sed comme suit -

$ cat /etc/passwd | sed '1, 5d' |more
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
$

La commande ci-dessus sera appliquée sur toutes les lignes de 1 à 5. Cela supprime les cinq premières lignes.

Essayez les plages d'adresses suivantes -

Sr.No. Gamme et description
1

'4,10d'

Les lignes à partir de la 4 e jusqu'à ce que le 10 e sont supprimés

2

'10,4d'

Seule la 10 e ligne est supprimée, car le sed ne fonctionne pas en sens inverse

3

'4,+5d'

Cela correspond à la ligne 4 du fichier, supprime cette ligne, continue de supprimer les cinq lignes suivantes, puis cesse sa suppression et imprime le reste

4

'2,5!d'

Cela supprime tout sauf à partir de la 2 ème à la 5 ème ligne

5

'1~3d'

Cela supprime la première ligne, passe les trois lignes suivantes, puis supprime la quatrième ligne. Sed continue d'appliquer ce modèle jusqu'à la fin du fichier.

6

'2~2d'

Cela indique à sed de supprimer la deuxième ligne, de passer à la ligne suivante, de supprimer la ligne suivante et de répéter jusqu'à ce que la fin du fichier soit atteinte

sept

'4,10p'

Les lignes à partir de 4 ème au 10 ème sont imprimées

8

'4,d'

Cela génère l'erreur de syntaxe

9

',10d'

Cela générerait également une erreur de syntaxe

Note - Lors de l'utilisation du p action, vous devez utiliser le -noption pour éviter la répétition de l'impression de ligne. Vérifiez la différence entre les deux commandes suivantes -

$ cat /etc/passwd | sed -n '1,3p'
Check the above command without -n as follows −
$ cat /etc/passwd | sed '1,3p'

La commande de substitution

La commande de substitution, désignée par s, remplacera toute chaîne que vous spécifiez par toute autre chaîne que vous spécifiez.

Pour remplacer une chaîne par une autre, le sed doit avoir les informations sur la fin de la première chaîne et le début de la chaîne de substitution. Pour cela, nous procédons à la réservation des deux chaînes avec la barre oblique (/) personnage.

La commande suivante remplace la première occurrence sur une ligne de la chaîne root avec la ficelle amrood.

$ cat /etc/passwd | sed 's/root/amrood/'
amrood:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
..........................

Il est très important de noter que sed ne remplace que la première occurrence sur une ligne. Si la racine de la chaîne apparaît plus d'une fois sur une ligne, seule la première correspondance sera remplacée.

Pour que le sed effectue une substitution globale, ajoutez la lettre g à la fin de la commande comme suit -

$ cat /etc/passwd | sed 's/root/amrood/g'
amrood:x:0:0:amrood user:/amrood:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
...........................

Drapeaux de substitution

Il existe un certain nombre d'autres indicateurs utiles qui peuvent être passés en plus du g drapeau, et vous pouvez en spécifier plusieurs à la fois.

Sr.No. Drapeau et description
1

g

Remplace tous les matchs, pas seulement le premier match

2

NUMBER

Remplace seulement NUMBER e match

3

p

Si une substitution a été effectuée, imprime l'espace du motif

4

w FILENAME

Si une substitution a été effectuée, écrit le résultat dans FILENAME

5

I or i

Correspondance insensible à la casse

6

M or m

En plus du comportement normal des caractères spéciaux des expressions régulières ^ et $, cet indicateur fait correspondre ^ la chaîne vide après une nouvelle ligne et $ pour correspondre à la chaîne vide avant une nouvelle ligne

Utilisation d'un autre séparateur de chaînes

Supposons que vous deviez effectuer une substitution sur une chaîne qui inclut la barre oblique. Dans ce cas, vous pouvez spécifier un séparateur différent en fournissant le caractère désigné après les.

$ cat /etc/passwd | sed 's:/root:/amrood:g'
amrood:x:0:0:amrood user:/amrood:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh

Dans l'exemple ci-dessus, nous avons utilisé : comme le delimiter au lieu de slash / parce que nous essayions de rechercher /root au lieu de la simple racine.

Remplacement par un espace vide

Utilisez une chaîne de substitution vide pour supprimer la chaîne racine du /etc/passwd déposer entièrement -

$ cat /etc/passwd | sed 's/root//g'
:x:0:0::/:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh

Substitution d'adresse

Si vous souhaitez remplacer la chaîne sh avec la ficelle quiet uniquement à la ligne 10, vous pouvez le spécifier comme suit -

$ cat /etc/passwd | sed '10s/sh/quiet/g'
root:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/quiet

De même, pour effectuer une substitution de plage d'adresses, vous pouvez faire quelque chose comme ceci -

$ cat /etc/passwd | sed '1,5s/sh/quiet/g'
root:x:0:0:root user:/root:/bin/quiet
daemon:x:1:1:daemon:/usr/sbin:/bin/quiet
bin:x:2:2:bin:/bin:/bin/quiet
sys:x:3:3:sys:/dev:/bin/quiet
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh

Comme vous pouvez le voir dans la sortie, les cinq premières lignes avaient la chaîne sh changé en quiet, mais le reste des lignes n'a pas été modifié.

La commande correspondante

Vous utiliseriez le p option avec la -n option pour imprimer toutes les lignes correspondantes comme suit -

$ cat testing | sed -n '/root/p'
root:x:0:0:root user:/root:/bin/sh
[[email protected] amrood]# vi testing
root:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh

Utilisation d'une expression régulière

Lors de la mise en correspondance de modèles, vous pouvez utiliser l'expression régulière qui offre plus de flexibilité.

Vérifiez l'exemple suivant qui correspond à toutes les lignes commençant par daemon puis les supprime -

$ cat testing | sed '/^daemon/d'
root:x:0:0:root user:/root:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh

Voici l'exemple qui supprime toutes les lignes se terminant par sh -

$ cat testing | sed '/sh$/d'
sync:x:4:65534:sync:/bin:/bin/sync

Le tableau suivant répertorie quatre caractères spéciaux très utiles dans les expressions régulières.

Sr.No. Caractère et description
1

^

Correspond au début des lignes

2

$

Correspond à la fin des lignes

3

.

Correspond à n'importe quel caractère

4

*

Correspond à zéro ou plusieurs occurrences du caractère précédent

5

[chars]

Correspond à l'un des caractères indiqués dans chars, où chars est une séquence de caractères. Vous pouvez utiliser le caractère - pour indiquer une plage de caractères.

Personnages correspondants

Regardez quelques expressions supplémentaires pour illustrer l'utilisation de metacharacters. Par exemple, le modèle suivant -

Sr.No. Expression et description
1

/a.c/

Correspond aux lignes contenant des chaînes telles que a+c, a-c, abc, match, et a3c

2

/a*c/

Correspond aux mêmes chaînes avec des chaînes telles que ace, yacc, et arctic

3

/[tT]he/

Correspond à la chaîne The et the

4

/^$/

Correspond aux lignes vides

5

/^.*$/

Correspond à une ligne entière quelle qu'elle soit

6

/ */

Correspond à un ou plusieurs espaces

sept

/^$/

Allumettes blank lignes

Le tableau suivant montre quelques jeux de caractères fréquemment utilisés -

Sr.No. Ensemble et description
1

[a-z]

Correspond à une seule lettre minuscule

2

[A-Z]

Correspond à une seule lettre majuscule

3

[a-zA-Z]

Correspond à une seule lettre

4

[0-9]

Correspond à un seul nombre

5

[a-zA-Z0-9]

Correspond à une seule lettre ou à un chiffre

Mots-clés de classe de caractère

Certains mots clés spéciaux sont généralement disponibles pour regexps, en particulier les utilitaires GNU qui utilisent regexps. Celles-ci sont très utiles pour les expressions régulières sed car elles simplifient les choses et améliorent la lisibilité.

Par exemple, les personnages a through z et les personnages A through Z, constituent l'une de ces classes de caractères ayant le mot-clé [[:alpha:]]

En utilisant le mot-clé de classe de caractères alphabet, cette commande imprime uniquement ces lignes dans le /etc/syslog.conf fichier commençant par une lettre de l'alphabet -

$ cat /etc/syslog.conf | sed -n '/^[[:alpha:]]/p'
authpriv.*                         /var/log/secure
mail.*                             -/var/log/maillog
cron.*                             /var/log/cron
uucp,news.crit                     /var/log/spooler
local7.*                           /var/log/boot.log

Le tableau suivant est une liste complète des mots-clés de classe de caractères disponibles dans GNU sed.

Sr.No. Classe de personnage et description
1

[[:alnum:]]

Alphanumérique [az AZ 0-9]

2

[[:alpha:]]

Alphabétique [az AZ]

3

[[:blank:]]

Caractères vides (espaces ou tabulations)

4

[[:cntrl:]]

Caractères de contrôle

5

[[:digit:]]

Numéros [0-9]

6

[[:graph:]]

Tous les caractères visibles (à l'exclusion des espaces)

sept

[[:lower:]]

Lettres minuscules [az]

8

[[:print:]]

Caractères imprimables (caractères non contrôlés)

9

[[:punct:]]

Caractères de ponctuation

dix

[[:space:]]

Espace blanc

11

[[:upper:]]

Lettres majuscules [AZ]

12

[[:xdigit:]]

Chiffres hexadécimaux [0-9 af AF]

Référencement Aampersand

le sed metacharacter &représente le contenu du modèle correspondant. Par exemple, disons que vous avez un fichier appeléphone.txt plein de numéros de téléphone, tels que les suivants -

5555551212
5555551213
5555551214
6665551215
6665551216
7775551217

Vous voulez faire le area code(les trois premiers chiffres) entourés de parenthèses pour une lecture plus facile. Pour ce faire, vous pouvez utiliser le caractère de remplacement esperluette -

$ sed -e 's/^[[:digit:]][[:digit:]][[:digit:]]/(&)/g' phone.txt
(555)5551212
(555)5551213
(555)5551214
(666)5551215

(666)5551216
(777)5551217

Ici, dans la partie du motif, vous faites correspondre les 3 premiers chiffres, puis utilisez & vous remplacez ces 3 chiffres par les parentheses.

Utilisation de plusieurs commandes sed

Vous pouvez utiliser plusieurs commandes sed dans une seule commande sed comme suit -

$ sed -e 'command1' -e 'command2' ... -e 'commandN' files

Ici command1 à travers commandNsont des commandes sed du type décrit précédemment. Ces commandes sont appliquées à chacune des lignes de la liste des fichiers donnée par les fichiers.

En utilisant le même mécanisme, nous pouvons écrire l'exemple de numéro de téléphone ci-dessus comme suit -

$ sed -e 's/^[[:digit:]]\{3\}/(&)/g'  \ 
   -e 's/)[[:digit:]]\{3\}/&-/g' phone.txt 
(555)555-1212 
(555)555-1213 
(555)555-1214 
(666)555-1215 
(666)555-1216 
(777)555-1217

Note - Dans l'exemple ci-dessus, au lieu de répéter le mot-clé de la classe de caractères [[:digit:]] trois fois, nous l'avons remplacé par \{3\}, ce qui signifie que l'expression régulière précédente est mise en correspondance trois fois. Nous avons également utilisé\ pour donner un saut de ligne et cela doit être supprimé avant que la commande ne soit exécutée.

Références arrière

le ampersand metacharacterest utile, mais encore plus utile est la possibilité de définir des régions spécifiques dans les expressions régulières. Ces régions spéciales peuvent être utilisées comme référence dans vos chaînes de remplacement. En définissant des parties spécifiques d'une expression régulière, vous pouvez ensuite faire référence à ces parties avec un caractère de référence spécial.

Faire back references, vous devez d'abord définir une région, puis vous référer à cette région. Pour définir une région, vous insérezbackslashed parenthesesautour de chaque région d'intérêt. La première région que vous entourez de barres obliques inverses est ensuite référencée par\1, la deuxième région par \2, etc.

En supposant phone.txt contient le texte suivant -

(555)555-1212
(555)555-1213
(555)555-1214
(666)555-1215
(666)555-1216
(777)555-1217

Essayez la commande suivante -

$ cat phone.txt | sed 's/\(.*)\)\(.*-\)\(.*$\)/Area \ 
   code: \1 Second: \2 Third: \3/' 
Area code: (555) Second: 555- Third: 1212 
Area code: (555) Second: 555- Third: 1213 
Area code: (555) Second: 555- Third: 1214 
Area code: (666) Second: 555- Third: 1215 
Area code: (666) Second: 555- Third: 1216 
Area code: (777) Second: 555- Third: 1217

Note - Dans l'exemple ci-dessus, chaque expression régulière entre parenthèses serait référencée à nouveau par \1, \2etc. Nous avons utilisé\pour donner un saut de ligne ici. Cela doit être supprimé avant d'exécuter la commande.