1
votes

Comment parcourir les chaînes d'ouverture et de fin dans un fichier bash?

J'écris un script shell pour parcourir les chaînes et faire écho aux correspondances si le mot est présent dans ce testcase.

J'ai un fichier qui ressemble à

TestCase_one
No matches
TestCase_TWo
.
.
  matched lines
.
.

dans ce fichier ci-dessus, je veux vérifier un mot particulier pour chaque testcase et echo correspondent si ce mot est présent, pour cela, je veux parcourir le fichier pour chaque testcase, puis passer étape par étape à la fin du fichier

Y a-t-il un moyen de commencer à grepping pour un mot entre TestCase_one et TestCase_one Passed, etc. comme

/*
  some build info #which are not matter of interest
*/
Test: TestCase_one
.
.
   output of that testcase 
   #TestCase_one name will not be present in btw
.
.
TestCase_one passed 
Test: TestCase_two
.
.
   output of that testcase
.
.
   TestCase_two passed 
   many testcases in this pattern
/*
   some thread info
*/

merci d'avance


1 commentaires

awk peut-il être utilisé pour y parvenir?


3 Réponses :


0
votes

Je suppose que vous ce qui est le suivant:

Entre «Test: Testcase» et «TestCase _. * passé», recherchez la chaîne «foo». Imprimez les lignes correspondantes s'il y a une correspondance.

Pourriez-vous simplement faire:

cat file |
  perl -ne '/^Test: Testcase start/ .. /Test case end/ and /^Test: Testcase start|foo/ and print'

Cela ne correspondrait pas parfaitement à votre résultat attendu (par exemple "Aucune correspondance "ne sera pas imprimé - il n'y aura tout simplement aucune correspondance), mais c'est assez proche et très simple.

Si vous ne voulez pas tous les cas de test mais que vous voulez en regarder un seul, cela pourrait fonctionner pour vous:

cat file |
  perl -ne '/^Test: Testcase start/ .. /Test case end/ and /foo/ and print'

Il recherchera foo mais uniquement entre Test: Testcase start et Test case fin . Si vous souhaitez inclure la ligne de départ dans la sortie, utilisez:

cat bigfile | grep -E '(foo|^Test: TestCase)'


8 commentaires

chat trinity.log | grep -E '(LEAK | ^ Test: SYNC_LOST_TestCase)' il imprime tout le toto du fichier, ai-je fait quelque chose de mal? la raison pour laquelle je veux passer en boucle est que la présence de foo dans certains cas de test n'est pas un problème et dans certains c'est une erreur pour cela, je veux vérifier s'il y a un foo dans les cas de test d'intérêt. merci la réponse


Peut-être devriez-vous jeter un œil à consentp, esp. son option -d, qui pourrait être utilisée ici, par exemple comme convenu -d '^ Test:' 'b # w' FILE. Lisez sa page de manuel, en particulier. sur la forme du modèle de recherche.


@Roadowl qui semble prometteur, mais d'accord n'existe pas dans mon projet, ce script sera utilisé par de nombreux développeurs dans ce projet (si je suis capable de le terminer) je ne pense pas qu'ils veulent tous installer d'accordp dans le minuscule objectif ce script sert merci!


@kuchu Toutes les lignes de départ commencent-elles par "Test: SYNC_LOST_TestCase"? Si ce n'est pas le cas, remplacez-le par ce que chaque ligne de départ des cas de test commence.


Avez-vous csplit (1)? Vous pouvez diviser le fichier en fichiers plus petits, chacun avec un enregistrement, puis grep ces fichiers. Par exemple. csplit --prefix = 'test-' --suffix-format = '% 06d' $ FILE '/ ^ Test: /' '{*}'


@Roadowl j'ai csplit, mais comment définir les limites dans ce domaine? le préfixe et le suffixe sont pour le nom du fichier à droite si je ne suis pas mal compris, csplit --prefix = 'test-' --suffix-format = '% 06d' trinity.log '/ ^ TestCase: /' ' {*} ' j'ai utilisé ceci puis j'ai tout dans un autre nom de fichier test-00000


Quand j'exécute la commande sur votre fichier comme je l'ai dit, csplit --prefix = 'test-' --suffix-format = '% 06d' $ FILE '/ ^ Test: /' '{*}' alors j'obtiens trois fichiers , test-000000 (58 octets), test-000001 (125 octets) et test-000002 (138 octets). test-000000 est le truc "quelques informations de construction", et les deux autres sont TestCase 1 et TestCase deux, que vous pouvez maintenant grep individuellement.


@Roadowl je l'ai essayé sur l'exemple de fichier journal que j'ai fourni, il a juste fait ce qui était demandé, mais dans le fichier journal d'origine, si j'applique le même csplit pour ce mot «Test:» étonnamment cela n'a pas fonctionné, j'ai remplacé Test: avec kuchu: pour voir si cela apporte des modifications, il a copié tout le fichier en un seul. mais faut-il avoir le mot Test: comme première lettre de la ligne ?? puisque dans mon fichier journal, le mot Test: vient après les horodatages et le nom du composant



0
votes

Il y a quelque temps, j'avais besoin de quelque chose comme ça, donc j'ai ceci qui pourrait vous aider -

    /*
      some build info #which are not matter of interest
    */
    Test: TestCase_one
    .
    .
       output of that testcase
    .
    .
    .
    TestCase_one passed
    Test: TestCase_two
    .
    .
       output of that testcase
    .
    .
    TestCase_two passed
       many testcases in this pattern
    /*
       some thread info
    */

Le sample.txt que j'ai utilisé est - p >

    #!/bin/bash

    checking_start=1 # flag for start of test case
    processing=0 # flag for processing a test case

    while IFS="" read -r p || [ -n "$p" ]; do # "p" is line in text file
        if [ $checking_start -eq 1 ]; then # checking for test case start
            mystartstr=`echo "$p" | grep Test: ` 
            if [ -z "$mystartstr" ]; then # if "mystartstr" is empty, continue
                echo "Non-related"
            else
                echo "Started processing.." # else set processing flag
                processing=1 # processing now true
                checking_start=0 # checking start of test case flag- false
            fi
        elif [ $processing -eq 1 ]; then  # if processing come here
            myendstr=`echo "$p" | grep TestCase_` # checking end of test case string
            if [ -z "$myendstr" ]; then # if end test case string empty, continue processing
                echo "Processing.." # This is where you will put your grep
            else
                echo "Ended processing.."  # Else end processing
                processing=0 # processing flag set as false
                checking_start=1 # start checking for new test case start
            fi
        else
            echo "No where.. Should never come here"
        fi
    done < sample.txt # Piping your text file here


11 commentaires

pouvez-vous s'il vous plaît expliquer ce que fait l'extrait de code ci-dessus, je n'ai pas compris ce que celui-ci a essayé de faire (je viens de commencer avec le script shell) merci pour la réponse de toute façon


@kuchu oh je vais ajouter des commentaires alors


@kuchu J'ai ajouté des commentaires en espérant que cela aide.


Je n'ai toujours pas compris comment p sait par où commencer (ou dois-je créer un tableau de cas de test et les affecter à p), est-ce que grep "fuite" trinity.log est placé après le traitement de l'écho grep entre la fin et le début du testcase? et à la place de sample.txt, j'ai conservé trinity.log ou devrait-il être sample.txt | trinity.log en ajoutant uniquement la ligne et le fichier grep à la fin, j'ai a fini par imprimer des termes en boucle infinie plusieurs fois, le myendstr peut-il être utilisé pour afficher le nom du testcase comme echo -e $ {myendstr} suivi de grep thing.


@kuchu La dernière ligne est l'endroit où j'alimente le fichier dans la boucle while et p commence à partir de la ligne 1 du fichier et s'exécute jusqu'à ce qu'il atteigne la dernière ligne. Si votre fichier est trinity.log , remplacez sample.txt par celui-ci. myendstr est la condition indiquant que ce cas de test a été traité. Il devrait renvoyer vide à moins que ce ne soit la ligne comme TestCase_two passé .


Je ne sais pas si je fais les choses correctement ou pas (je n'ai fait que deux changements au code que vous avez posté, l'un alimente le fichier, un autre est grep -F '[LEAK]:' path / trinity.log; après echo "Processing ..", mais cela entre dans une boucle infinie je lui ai donné cinq minutes pour s'arrêter mais il était toujours en cours d'impression de tous les matchs @ViKiG


@kuchu combien de fichiers de lignes s'agit-il? Le sample.txt que j'ai utilisé fonctionne. Je vais coller le sample.txt pour vous dans ma réponse.


Dans mon programme, j'ai mis la condition pour myendstr comme grep TestCase_ . Voyez si c'est ce dont vous avez besoin. De même, pour mystartstr aussi, vous devez vérifier la condition requise pour le fichier texte trinity.log .


De plus, vous dites que vous avez ajouté une ligne sous echo Processing .. comme grep -F '[LEAK]:' path / trinity.log . Vous devez changer cette ligne. Vous avez déjà la ligne de trinity.log qui est $ p dans le programme ci-dessus. Si vous voulez grep une ligne, utilisez echo "$ p" | grep someConditionString


il faisait 5000 lignes et 14 TestCases dedans, il grandira à mesure que d'autres TestCases seront ajoutés à l'avenir, j'utilise grep "_TestCase PASSED" lorsque j'exécute la commande grep ci-dessus sur le fichier journal i avoir exactement 14 résultats pour 14 cas de test différents, j'ai changé echo "$ p" | grep -F '[LEAK]:' chemin / trinity.log; je ne sais pas pourquoi il se termine dans les toilettes infinies.


Dans tous les cas, il ne doit pas entrer en boucle infinie. Si la taille du fichier est de 5 000 lignes, le programme devrait s'arrêter. Supprimer, condition || [-n "$ p"] dans la boucle while .



0
votes

Une version awk:

awk <test.log -v k='MATCHWORD' -e '
    $1=="Test:" { print n=t=$2; next }
    t && $0~k   { n=0; print }
    $1==t && n  { t=0; print "No matches" }
'
  • k : variable contenant le mot à rechercher
  • t : variable contenant le nom du testcase
  • n : variable indiquant si mot non encore trouvé dans ce cas de test
  • $ 1 == "Test:" : début du testcase?
  • t && $ 0 ~ k : dans un cas de test et la ligne contient un mot?
  • $ 1 == t && n : fin du cas de test et mot non trouvé?


0 commentaires