Je veux trouver la ficelle
Time series prediction with ensemble models
j'utilise pdftotext "$file" - | grep "$string"
. Où $file
est le nom du fichier pdf et $string
est la chaîne 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 comme:
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 'universe'), qui prend en charge les correspondances sur plusieurs lignes, puis au lieu de rechercher la chaîne littérale.
Time series prediction with ensemble models
recherchez plutôt expression régulière compatible Perl (PCRE)
Time\s+series\s+prediction\s+with\s+ensemble\s+models
où \s+
représente un ou plusieurs caractères d'espacement (incluant les nouvelles lignes). Utilisation des fonctionnalités intégrées de substitution de chaînes du shell bash pour effectuer la dernière étape
pdftotext "$file" - | pcregrep -M "${string// /\\s+}"
Si vous ne pouvez pas utiliser pcregrep
, vous pourrez peut-être obtenir le résultat souhaité avec plain grep
avec le commutateur -z
: cela indique à grep
de prendre en compte l'entrée " "lignes" à délimiter par NUL
caractères plutôt que par des nouvelles lignes - dans ce cas, cela permet de traiter efficacement 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 "${string// /\\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 puisqu'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
#!/usr/bin/env python3
import subprocess
import sys
f = sys.argv[1]; string = 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 string
subtext = text.replace("\n", " "); size = len(string)
# in a while loop, find the matching string and set the last found index as a start for the next match
matches = []; start = 0
while True:
match = subtext.find(string, 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].strip())
search_pdf.py
Exécutez-le à l'aide de la commande:
python3 /path/to/search_pdf.py /path/to/file.pdf string_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' 'string 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:
string="Time series prediction with ensemble models"
pdftotext "$file" - | tr '\n' ' ' | grep -o "$string"
J'ai ajouté le -o
pour que grep
imprime uniquement la partie correspondante de la ligne. Sans cela, vous obtiendrez tout le contenu du fichier imprimé.
Une autre approche consisterait à utiliser le commutateur -z
de grep
qui lui dit 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 pas à moins que vous sachiez au préalable comment la chaîne a été divisée en plusieurs lignes.