web-dev-qa-db-fra.com

Utilisez la commande sed pour appliquer une condition afin de vérifier si un motif a été mis en correspondance

Je cherche la chaîne ::=BEGIN et je souhaite appliquer une condition pour vérifier si le mot a été trouvé.

Donc, ce que je veux dire est quelque chose dans ce sens:

if (sed command does find a match for "::=BEGIN")
then i=1 
else i=0

De plus, je veux que le 1 (pour oui trouvé) et le 0 (non trouvé) soit mis dans la variable "i".

Sil te plait aide moi. Fournissez également une explication à la solution! Merci!

7
SamFlynn

grepfait ce travail assez bien.

$ echo "::=BEGIN" > testfile1.txt

$ grep "::=BEGIN" -q testfile1.txt && echo "FOUND"
FOUND

$ grep "::=BEGIN" -q testfile1.txt && echo "FOUND" || echo "NOTFOUND"
FOUND

$ grep "whever" -q testfile1.txt && echo "FOUND" || echo "NOTFOUND"
NOTFOUND

Le code ne fait que lancer une recherche silencieuse dans le sous-shell. &&, ou l'opérande AND logique, vérifie si la première commande a abouti. Si c'est le cas, il exécute echo "FOUND". || vérifie si cet écho a été exécuté, c'est-à-dire si nous avons trouvé quelque chose. Le second écho ne s'exécute que si la première commande a échoué.

Voici une version awkname__:

$ awk '{i="NOTFOUND";if($0~/::=BEGIN/) i="FOUNDIT";exit } END { print i}' testfile1.txt
FOUNDIT

$ awk '{i="NOTFOUND";if($0~/whatevs/) i="FOUNDIT";exit } END { print i}' testfile1.txt
NOTFOUND

L'idée de base est de définir isur NOTFOUNDet, si nous trouvons la chaîne, remplacez-la par FOUNDITname__. À la fin, une fois le premier fichier traité terminé, nous imprimerons iet nous dirons si nous avons trouvé quelque chose ou non.

Edit: Dans le commentaire que vous avez indiqué, vous souhaitez placer le résultat dans une variable. Shell fournit déjà une variable qui indique le statut de sortie de la commande précédente, $0. Le statut de sortie 0 signifie succès, tout le reste - échec. Par exemple,

$ grep "::=BEGIN" -q testfile1.txt  
$ echo $?
0

Si vous souhaitez utiliser le statut de sortie dans une variable, vous pouvez le faire comme suit: MYVAR=$(echo $?). Rappelez-vous, $? signaler le statut de sortie de la commande précédente. Donc, vous devez utiliser ceci juste après la commande grep.

Si vous souhaitez continuer à utiliser mes précédentes lignes unies awk et grep, vous pouvez utiliser la même astuce MYVAR=$() et placer la commande de votre choix entre les accolades. La sortie sera affectée à la variable MYVARname__.

6

Avec un GNU sed --- (tel qu'il est installé par défaut sur tout système Ubuntu):

{ sed -n '/::=BEGIN/Q 1'; i=$?; } <infile

Quelques faits sur cette réponse:

  1. sedQuits dès que le toute première correspondance se trouve n'importe où dans le fichier - ce qui signifie qu'il ne perd plus de temps à lire l'info-fichier.

  2. sedretourne dans son code de sortie la valeur numérique ou 1 en fonction de la possibilité ou non de la trouver l'expression rationnelle adressée.

  3. $i est défini sur sed's s return on exit.

  4. Le groupement {; } est utilisé pour gérer de manière robuste toute erreur de redirection possible - $i n'est pas défini dans le cas où le shell ne peut pas ouvrir le fichier, évitant ainsi les faux positifs.

Ceci ne devrait probablement pas être préféré à grep -q, cependant, ce qui peut fondamentalement aussi faire tout ce qui précède ((si inverse), faites-le POSIXly et généralement plus rapidement.

La réponse grep -q déjà donnée est très bonne, mais un petit doute:

grep -q pattern ./infile; i=$((!$?))
5
mikeserv

Vous pouvez utiliser ceci:

#!/bin/bash
while IFS= read -r line; do
    case "$line" in *::=BEGIN*) i=1 && break;;         
                               *) i=0
    esac
done <file.txt

Ceci recherchera le fichier file.txt ligne par ligne et si une correspondance de ::=BEGIN est trouvée, il définira la variable i=1 et se fermera. Si aucune correspondance n'est trouvée, la variable sera définie sur i=0.

4
heemayl

Ma version sedname__

sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}'

à stocker dans une variable iname__:

i=$(sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}')

Exemple:

$ echo "::=BEGIN" > foo
$ echo "::=BEGIN" >> foo
$ sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}' 
1
$ echo "::=NOT_BEGIN" > foo
$ sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}'
0
$ echo "::=BEGIN" >> foo
$ sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}' 
1

Explication:

  • Si ::=BEGIN est trouvé, imprimez un 1 et passez à nextname__
  • Si ::=BEGIN est introuvable, imprimez 0
3
A.B.

sed (Stream Editeur) n'est pas l'outil idéal pour ce genre de choses: vous pouvez simplement utiliser une instruction bashif pour faire correspondre votre entrée à une expression régulière:

#!/bin/bash

#...
input="$(< inputfile)"
[[ "$input" =~ ::=BEGIN ]] && i=1 || i=0
#...
  • input="$(< inputfile)": assigne le contenu de inputfile à la variable $input
  • [[ "$input" =~ ::=BEGIN ]] && i=1 || i=0: fait correspondre la regex ::=BEGIN au contenu de la variable $input; s'il y a correspondance, il attribue 1 à $i, sinon il attribue 0 à $i
2
kos