Ich habe eine Zeichenfolge wie: "thisissometext"
. Ich möchte alle Textdateien in einem bestimmten Verzeichnis (rekursiv) finden, die diese Zeichenfolge oder Variationen davon mit Leerzeichen und/oder Zeilenumbrüchen in der Mitte enthalten. Beispielsweise sollte eine Textdatei, die , "this is sometext"
oder enthält "this\n issometext"
, "this\n isso metext"
in der Suche angezeigt werden. Wie kann ich das tun?
Antwort1
Bei den neueren Versionen von GNU grep
(die diese -z
Option haben) können Sie diesen Einzeiler verwenden:
find . -type f -exec grep -lz 'this[[:space:]]*is[[:space:]]*some[[:space:]]*text' {} +
Beachten Sie, dass Leerzeichen nur zwischen den Wörtern stehen dürfen.
Wenn Sie einfach alle Dateien rekursiv ab dem aktuellen Verzeichnis durchsuchen möchten, brauchen Sie nicht find
, Sie können einfach grep -r
(rekursiv) verwenden. find
kann verwendet werden, um selektiv nach Dateien zu suchen, z. B. um Dateien auszuwählen, deren Verzeichnis ausgeschlossen werden soll. Also einfach:
grep -rlz 'this[[:space:]]*is[[:space:]]*some[[:space:]]*text' .
Der Haupttrick besteht hier darin
-z
, dass jede Zeile des Eingabestroms, die mit ASCII NUL endet, statt als neue Zeile behandelt wird, sodass wir Zeilenumbrüche mithilfe der üblichen Methoden abgleichen können.[[:space:]]
Das Zeichenklassenmuster gibt alle Leerzeichen an, einschließlich Leerzeichen, Tabulatoren, CR, LF usw. Wir können es also verwenden, um alle Leerzeichen abzugleichen, die zwischen den Wörtern stehen können.grep -l
druckt nur die Dateinamen, die eines der gewünschten Muster aufweisen. Wenn Sie auch die Übereinstimmungen drucken möchten, verwenden Sie-H
anstelle von-l
.
Wenn die Leerzeichen andererseits an beliebigen Stellen und nicht zwischen den Wörtern stehen können, würde dies sein gutes Aussehen verlieren:
grep -rlz
't[[:space:]]*h[[:space:]]*i[[:space:]]*s[[:space:]]*i[[:space:]]*\
s[[:space:]]*s[[:space:]]*o[[:space:]]*m[[:space:]]*e[[:space:]]*\
t[[:space:]]*e[[:space:]]*x[[:space:]]*t' .
Mit -P
der Option (PCRE) können Sie das [[:space:]]
durch Folgendes ersetzen \s
(das würde viel schöner aussehen):
grep -rlzP 't\s*h\s*i\s*s\s*i\s*s\s*s\s*o\s*m\s*e\s*\
t\s*e\s*x\s*t' .
sed
Die beste Option wäre, den Vorschlag von @steeldriver zu verwenden, um das Muster für uns zu generieren:
grep -rlzP "$(sed 's/./\\s*&/2g' <<< "thisissometext")" .
Antwort2
Sie können alle Leerzeichen löschen und sie greppen:
tr -d '[[:space:]]' < foo | grep thisissometext
Erweiterung:
find . -type f -exec bash -c 'for i; do tr -d "[[:space:]]" < "$i" | grep -q thisissometext && printf "%s\n" "$i"; done' _ {} +
Der bash
erweiterte Befehl:
for i
do
tr -d "[[:space:]]" < "$i" |
grep -q thisissometext &&
printf "%s\n" "$i"
done
Dies durchläuft eine Schleife über alle Argumente und verwendet den obigen Test.
Antwort3
Der folgende Code durchsucht ein Verzeichnis rekursiv nach Dateien und entfernt alle Vorkommen von " "
und "\n"
. Wenn die Zeichenfolge im verbleibenden Text vorhanden ist, gibt es eine Übereinstimmung. Dies bedeutet, dass die Leerzeichen/Zeilenumbrüche aufbeliebigPosition in der Zeichenfolge innerhalb Ihrer Datei(en).
Was es macht
Wenn übereinstimmende Dateien gefunden werden, werden diese zusammen mit ihren Pfaden im Terminal ausgegeben, etwa:
/home/jacob/Bureaublad/testmap/test2.txt
/home/jacob/Bureaublad/testmap/Naamloze map 2/test1.txt
Das Try/Except-Feature habe ich eingebaut, um zu verhindern, dass das Skript abbricht, wenn es auf eine nicht lesbare Datei stößt.
Das Drehbuch
#!/usr/bin/env python3
import os
import sys
s = sys.argv[2]
for root, dirs, files in os.walk(sys.argv[1]):
for file in files:
file = root+"/"+file
try:
if s in open(file).read().replace(" ", "").replace("\n",""):
print(file)
except:
pass
Wie benutzt man
- Kopieren Sie das Skript in eine leere Datei und speichern Sie es unter
find_string.py
Führen Sie es mit dem Verzeichnis und der Zeichenfolge als Argumente aus:
python3 /path/to/find_string.py <directory> <string_to_find>
Wenn entweder die Zeichenfolge oder das Verzeichnis Leerzeichen enthält, verwenden Sie Anführungszeichen:
python3 /path/to/find_string.py '<directory>' '<string_to_find>'
Notiz
Das Skript findet Dateien mit der Zeichenfolge, die entweder Leerzeichen oder Zeilenumbrüche enthält. Es kann mit anderen Zeichen/Zeichenfolgen (z. B. Tabulatoren) in der Zeile erweitert werden:
if s in open(file).read().replace(" ", "").replace("\n",""):
Antwort4
Sie können grep -i --recursive 'word1\|word2' *
und awk '/word1/,/word2/'
können verwendet werden, um mit der Newline umzugehen