2
votes

Rechercher la première occurrence d'une chaîne après la première occurrence d'une autre chaîne avec bash

J'ai un fichier d'entrée qui ressemble à ceci et je veux la première occurrence de mots mais seulement après la première occurrence de spécial

Les nombres sont seulement là donc je sais que j'ai la bonne chaîne

EDIT: j'ai réalisé qu'il importait que les chaînes aient des /

grep -m1 special file | grep -m1 words file 

awk 'NR==1,/special/ && NR==1,/words/ {print $0}' file 

J'essaye de trouver la première occurrence de "mot" après avoir trouvé la première occurrence de "spécial"

Le résultat doit être

words/i/need/you/i.really.need.you #4

J'ai essayé ce qui suit

words/and/stuff #1
words/more #2
some/other/words #3
special/this #1
words/i/need/you/i.really.need.you #4
special/cool #2 
words/random #5


3 commentaires

Vous avez failli l'avoir ... grep -A 99999 fichier spécial | grep -m1 mots


@MarkSetchell WOW !!!! C'est simple et direct !!!!! Je finirai par utiliser ça.


J'apprends à quel point il est ignorant de créer des fichiers d'entrée simulés. Je vais commencer à mettre le fichier d'entrée littéral pour éviter les maux de tête des deux parties. C'est en fait pour un fichier xml et cette commande grep renvoie les deux greps non seulement le dernier, mais je peux le résoudre à partir de là, il peut être un peu redondant. Mais mal jouer avec.


3 Réponses :


0
votes

Script sed dédié rapide

Vous pourriez utiliser pour ceci:

w1=false
while read line ;do
    if [ "$line" ] ;then
        if $w1 && [ -z "${line//*words*}" ] ;then
            echo $line
            break
        fi
        if [ -z "${line//*special*}" ] ;then w1=true ;fi
    fi
done <file

Affiche, à partir de votre exemple:

words #4
  • De la ligne contenant special , à la fin de l'entrée,

    • si la ligne contient word , alors quittez
    • sinon supprimer ligne.
  • autre, supprimer ligne.

Pure , comme le titre de votre question sur bash:

sed -e  '/special/,${ /word/q;d };d' file

3 commentaires

Terriblement désolé, j'ai réalisé plus tard que j'ai des problèmes qui affectent le code


@goosegoose Ce n'est pas grave! Avez-vous essayé cela? Vous pouvez utiliser autre chose que / si nécessaire! Ou échapper : / special \ / cool /


@goosegoose Je viens de tester maintenant votre entrée modifiée! Mon code fonctionne toujours !!



1
votes

Essayez :

$ awk '/special/{f=1} f && /words\/i\/need/ {print; exit}' file 
words/i/need/you/i.really.need.you #4

Comment ça marche:

  • /special/{f=1}

    Si la ligne actuelle correspond à special , définissez la variable f sur 1

  • f && / words / {print; exit}

    Si f est différent de zéro et que la ligne courante correspond à mots , alors imprimez la ligne courante et quittez.

Mots avec des barres obliques

Si le mot que vous voulez faire correspondre n'est pas simplement entouré de barres obliques mais les inclut, le même code fonctionne. Il faut juste échapper aux barres obliques. Par exemple, si nous recherchons le mot words / i / need après special:

$ awk '/special/{f=1} f && /words/ {print; exit}' file 
words/i/need/you/i.really.need.you #4


2 commentaires

Terriblement désolé, j'ai réalisé plus tard que j'ai des problèmes qui affectent le code


@goosegoose Merci pour l'avis. Avec le fichier d'entrée mis à jour, le même code fonctionne toujours ici.



0
votes

Pourriez-vous essayer de suivre.

awk '
$0=="words"{
  count++
  if(special_count==1){
    print "String words count is: "count
    exit
  }
}
/special/{
  special_count++
}
'  Input_file


2 commentaires

Terriblement désolé, j'ai réalisé plus tard que j'ai des problèmes qui affectent le code


@goosegoose, désolé je ne l'ai pas compris; si votre chaîne n'est pas mots alors changez-la dans mon code en mot ?