Comment trouver une chaîne de plusieurs lignes dans un script shell?

Je veux trouver la ficelle

Time series prediction with ensemble models 

j’utilise pdftotext "$file" - | grep "$ssortingng" pdftotext "$file" - | grep "$ssortingng" .where $file est le nom du fichier pdf et $ssortingng est la $ssortingng ci-dessus.Il peut trouver la ligne si la chaîne entière contient dans une ligne.Mais elle ne peut pas trouver la ligne suivante:

 Time series prediction with ensemble models 

comment puis-je le résoudre.Je suis nouveau sur linux. donc, l’explication détaillée est appréciée.Merci d’avance.

Une solution possible pourrait consister à remplacer grep par pcregrep (disponible dans le référentiel ‘univers’), qui prend en charge les correspondances sur plusieurs pcregrep , puis à la place de rechercher la chaîne littérale.

 Time series prediction with ensemble models 

recherchez plutôt l’ expression régulière compatible Perl (PCRE)

 Time\s+series\s+prediction\s+with\s+ensemble\s+models 

\s+ représente un ou plusieurs caractères d’espacement (y compris les nouvelles lignes). Utiliser les capacités de substitution de chaînes intégrées du shell bash pour effectuer la dernière étape

 pdftotext "$file" - | pcregrep -M "${ssortingng// /\\s+}" 

Si vous ne pouvez pas utiliser pcregrep vous pourrez peut-être obtenir le résultat souhaité en utilisant grep simple avec le commutateur -z : ceci indique à grep de considérer les “lignes” d’entrée comme délimitées par des caractères NUL plutôt que par des lignes, dans ce cas , ce qui en fait traite l’entrée entière comme une seule ligne. Donc, par exemple, si vous voulez seulement imprimer les correspondances (sans contexte)

 pdftotext "$file" - | grep -zPo "${ssortingng// /\\s+}" 

Avec Python, beaucoup peut être fait …

Si je le relise plus tard, je pourrai probablement faire une optimisation, mais lors de mes tests, le script ci-dessous fait le travail.

Testé sur un fichier:

 Monkey eats banana since he ran out of peanuts Monkey eats banana since he ran out of peanuts really, Monkey eats banana since he ran out of peanuts A lot of useless text here… Have to add some lines for the sake of the test. Monkey eats banana since he ran out of peanuts 

à la recherche d’une chaîne de caractères “Le singe mange de la banane depuis qu’il n’a plus d’arachides”, il affiche:

 Found matches -------------------- [line 1] Monkey eats banana since he ran out of peanuts [line 2] Monkey eats banana since he ran out of peanuts [line 5] Monkey eats banana since he ran out of peanuts [line 9] Monkey eats banana since he ran out of peanuts 

Le script

 #!/usr/bin/env python3 import subprocess import sys f = sys.argv[1]; ssortingng = sys.argv[2] # convert to .txt with your suggestion subprocess.call(["pdftotext", f]) # read the converted file text = open(f.replace(".pdf", ".txt")).read() # editing the file a bit for searching options / define th length of the searched ssortingng subtext = text.replace("\n", " "); size = len(ssortingng) # in a while loop, find the matching ssortingng and set the last found index as a start for the next match matches = []; start = 0 while True: match = subtext.find(ssortingng, start) if match == -1: break else: matches.append(match) start = match+1 print("Found matches\n"+20*"-") for m in matches: # print the found matches, replacing the edited- in spaces by (possibly) original \n print("[line "+str(text[:m].count("\n")+1)+"]\n"+text[m:m+size].ssortingp()) 

Pour l’utiliser:

  1. copiez le script dans un fichier vide, enregistrez-le sous search_pdf.py
  2. Exécutez-le à l’aide de la commande:

     python3 /path/to/search_pdf.py /path/to/file.pdf ssortingng_to_look_for 

Inutile de mentionner que vous devez utiliser des guillemets si le chemin ou la chaîne recherchée contient des espaces:

 python3 '/path to/search_pdf.py' '/path to/file.pdf' 'ssortingng to look for' 

Une autre approche suggérée par steeldriver dans les commentaires consiste à remplacer tous les sauts de ligne par des espaces, en convertissant la sortie de pdftotext en une longue ligne et en recherchant que:

 ssortingng="Time series prediction with ensemble models" pdftotext "$file" - | tr '\n' ' ' | grep -o "$ssortingng" 

J’ai ajouté le -o pour que grep n’imprime que la partie correspondante de la ligne. Sans cela, vous obtiendrez tout le contenu du fichier imprimé.


Une autre approche consisterait à utiliser le commutateur -z grep qui lui indique d’utiliser \0 au lieu de \n pour définir des lignes. Cela signifie que toute l’entrée sera traitée comme une “ligne” unique et que vous pouvez utiliser des expressions régulières compatibles Perl ou étendues pour la faire correspondre:

 $ printf 'foo\nbar\nbaz\n' | grep -oPz 'foo\nbar' foo bar 

Ceci n’aidera cependant que si vous savez à l’avance comment la chaîne a été divisée en plusieurs lignes.