Brauchen Sie Hilfe beim Scannen von Textdateien und finden Sie alle Wörter zwischen zwei Mustern. Wie gesagt, wenn wir eine .sql-Datei haben, müssen Sie alle Wörter zwischen 'und' wo 'suchen und finden. Grep kann nur 1 Zeile gleichzeitig scannen. Für diese Anforderung Welches ist das beste Unix-Skript? sed, awk hat diese Eigenschaften? Auf Beispiele zu verweisen wird sehr geschätzt.Grep Access Mehrere Zeilen, finde alle Wörter zwischen zwei Mustern
Antwort
Sed hat dies:
sed -n -e '/from/,/where/ p' file.sql
Drucke alle Linien zwischen einer Linie mit einem from
und eine Zeile mit einem where
.
Für etwas, das Linien, die beide aus und wo können sein: Diese
#!/bin/sed -nf
/from.*where/ {
s/.*\(from.*where\).*/\1/p
d
}
/from/ {
: next
N
/where/ {
s/^[^\n]*\(from.*where\)[^\n]*/\1/p
d
}
$! b next
}
(geschrieben als sed-Skript) ist etwas komplexer, und ich werde versuchen, um die Details zu erklären. Die erste Zeile wird in einer Zeile ausgeführt, die sowohl from
als auch where
enthält. Wenn eine Zeile mit diesem Muster übereinstimmt, werden zwei Befehle ausgeführt. Wir verwenden den Ersetzungsbefehl s
, um nur die Teile zwischen from und wo zu extrahieren (einschließlich from und wo). Das Suffix in diesem Befehl gibt die Zeile aus. Der Löschbefehl löscht den Musterbereich (den Arbeitspuffer), lädt die nächste Zeile und startet das Skript neu.
Der zweite Befehl startet die Ausführung einer Reihe von Befehlen (gruppiert nach geschweiften Klammern), wenn eine Zeile gefunden wird, die from
enthält. Im Grunde bilden die Befehle eine Schleife, die Zeilen von der Eingabe an den Musterbereich anfügt, bis eine Zeile mit where
gefunden wird oder bis wir die letzte Zeile erreichen.
Der Befehl ":
" erstellt eine Beschriftung, eine Markierung im Skript, die es uns ermöglicht, "zurückzuspringen", wann immer wir wollen. Der Befehl N
liest eine Zeile aus der Eingabe und hängt sie an den Musterbereich an (die Zeilen werden durch ein Zeilenvorschubzeichen getrennt).
Wenn ein where
gefunden wird, können wir den Inhalt des Musterbereichs drucken, aber zuerst müssen wir ihn mit dem Ersatzbefehl reinigen. Es ist analog zu dem, das vorher verwendet wurde, aber wir ersetzen nun das führende und nachfolgende .*
durch [^\n]*
, was sed sagt, dass nur Nicht-Newline-Zeichen übereinstimmen, was effektiv einem von in der ersten Zeile und einem wo in der letzten Zeile entspricht. Der Befehl d
löscht dann den Musterbereich und startet das Skript in der nächsten Zeile neu.
Der Befehl b
springt auf ein Etikett, in unserem Fall auf das Etikett next
. Die Adresse $!
besagt jedoch, dass sie in der letzten Zeile nicht ausgeführt werden darf, damit wir die Schleife verlassen können. Wenn Sie die Schleife auf diese Weise verlassen, haben wir keine entsprechende where
gefunden, so dass Sie sie möglicherweise nicht drucken möchten.
Beachten Sie jedoch, dass dies einige Nachteile hat. Die folgenden Fälle werden nicht wie erwartet behandelt:
from ... where ... from
from ... from
where
from
where ... where
from
from
where
where
Die Verarbeitung dieser Fälle erfordert mehr Code.
Hope this =)
unkompliziert, aber ich denke nicht, dass es was OP braucht .... – Kent
Danke, rettete mir einen Haufen RTFM'ing :-) –
eine Idee für die Zeilennummer wird auch am Anfang der Zeile mit der übereinstimmenden Zeile gedruckt, wenn das Muster übereinstimmt –
Mit GNU awk hilft so können Sie die RS auf ein RE gesetzt:
gawk -v RS='[[:space:]]+' '
/where/ { found=0 }
found { print }
/from/ { found=1 }
' file
Die obige Sie die "von" nicht davon ausgegangen, wollen und "where" gedruckt, Verschieben Sie die Linien falls nötig, um etwas anderes zu tun.
Falls es hilft, beschreiben die folgenden Idiome, wie eine Reihe von Aufzeichnungen ein bestimmtes Muster gegeben auszuwählen übereinstimmen:
von einem Mustera) Drucken Sie alle Datensätze:
awk '/pattern/{f=1}f' file
b) drucken Sie alle Aufzeichnungen nach einigen Mustern:
awk 'f;/pattern/{f=1}' file
c) Drucke des N-ten Datensatz nach einigen Mustern:
Druckawk 'c&&c--;/pattern/{c=N}' file
f) jeden Datensatz mit Ausnahme der:
awk 'c&&!--c;/pattern/{c=N}' file
d) Drucke jeder Datensatz außer dem N-ten Datensatz nach einigen Mustern:
awk 'c&&!--c{next}/pattern/{c=N}1' file
e) Drucken Sie die N Aufzeichnungen nach einigen Mustern N Datensätze nach einem Muster:
awk 'c&&c--{next}/pattern/{c=N}1' file
g) Drucken Sie das N reco rds von einem Muster:
awk '/pattern/{c=N}c&&c--' file
ich die Variablennamen aus „f“ geändert für „gefunden“ zu „c“ für „count“, wo angemessen wie ausdruck von dem, was die Variable tatsächlich ist.
Sie könnten hierfür ed
verwenden, dies ermöglicht positive und negative Offsets für den Regex-Bereich. Wenn die Eingabe:
seq 10 | tee > infile
1
2
3
4
5
6
7
8
9
10
Rohr im Befehl ed
:
<<< /3/,/6/p | ed -s infile
d.h. alles zwischen den Linien gedruckt enthalten 3
und 6
.
Ergebnis:
3
4
5
6
Um an jedem Ende eine weitere Zeile zu erhalten:
<<< /3/-1,/5/+1p | ed -s infile
Ergebnis:
2
3
4
5
6
7
Oder umgekehrt:
<<< /3/+1,/6/-1p | ed -s infile
Ergebnis:
4
5
Um nur einen String innerhalb von zwei bestimmten Strings, entlang der Linien von awk
zurückkehren (ohne verrückt zu bekommen) Ich laufe gerade dieses sehr flach Skript, Ausführlichkeit im Schlepptau:
.\gnucoreutils\bin\awk "{startstring = \"RETURN STUFF AFTER ME \"; endstring = \"RETURN STUFF BEFORE ME\"; endofstartstring = index($0,startstring)+length(startstring); print substr($0,endofstartstring,index($0,endstring)-endofstartstring)}" /dev/stdin
beachten Sie, dass ich bin mit cmd.exe
(der Befehlsinterpreter mit Windows) und the gnuwin32 awk, so beachten Sie die "doppelte Anführungszeichen" und^\ Escape-Zeichen^\:
GNU Awk 3.1.6
Copyright (C) 1989, 1991-2007 Free Software Foundation.
Bitte weisen Sie auf Fehler hin.
Beispiel:
echo "hello. RETURN STUFF AFTER ME i get returned RETURN STUFF BEFORE ME my face is melting" | .\gnucoreutils\bin\awk "{startstring = \"RETURN STUFF AFTER ME \"; endstring = \" RETURN STUFF BEFORE ME\"; endofstartstring = index($0,startstring)+length(startstring); print substr($0,endofstartstring,index($0,endstring)-endofstartstring)}" /dev/stdin
i get returned
Ich konnte dies mit nur grep erreichen:
#> grep -A#### "start pattern" file | grep -B#### "end pattern"
Das Problem war, dass ich die richtige Menge an Linien zu finden, hatte in der A und B umfassen Optionen, die gleich sind. Hoffe, das hilft
- 1. Grep zwischen zwei Mustern in Code
- 2. Git Grep mehrere Wörter auf mehrere Zeilen
- 3. Grep ignoriert mehrere Zeilen
- 4. Fund Linien zwischen zwei Mustern sed Verwendung
- 5. Wie extrahiert man eine Zeichenfolge zwischen zwei Mustern in Bash
- 6. Alle Wörter zwischen zwei bestimmten Wörtern in einem Zeichenvektor extrahieren
- 7. Grep Regex: Liste alle Zeilen außer
- 8. grep Spiele zwischen zwei Dateien und konvertiert in Kleinbuchstaben
- 9. Erzeugt alle Daten zwischen zwei
- 10. Alle Spalten anzeigen, die zwischen zwei Zeilen wechseln
- 11. toggle 2 checkboxes zwischen zwei Zeilen über mehrere Spalten
- 12. Wie finden Sie alle Wörter zwischen Klammern?
- 13. Regex zwischen zwei mal
- 14. grep für nur Wörter in Großbuchstaben
- 15. finden mehrere Linien zwischen zwei Zeilen (regular expression)
- 16. Teil der Zeichenfolge zwischen zwei verschiedenen Mustern extrahieren
- 17. tcl regulärer Ausdruck, versucht, eine Zeichenfolge zwischen zwei Mustern herauszuziehen
- 18. Ersetze mehrzeilige Zeichenfolge zwischen zwei Mustern mit sed
- 19. Zeile zwischen zwei Zeilen einfügen
- 20. Datenrahmen Zeilen zwischen zwei Terminen
- 21. Python finde Wörter in nltk.tree
- 22. Unterschied zwischen egrep und grep
- 23. finde zwei Wörter in einer Zeichenfolge und kopiere alles zwischen ihnen
- 24. Grep Worte mit genau zwei Vokalen
- 25. C# - RegEx - Get Strings zwischen zwei Zeilen
- 26. Finde die minimale Differenz zwischen zwei Arrays
- 27. Finde n logarithmische Intervalle zwischen zwei Endpunkten
- 28. Access Select Top 1 gibt nicht alle Zeilen zurück
- 29. Wie finde ich einen TextRange in RichTextBox (zwischen zwei TextPointers)
- 30. Warum grep Spiel alle Zeilen für das Muster „\ '“
können Sie einen Beispiel-SQL-Inhalt einfügen? z.B. wie viele von ... wo in deiner Datei? Gibt es den Fall, dass "von" und "wo" in derselben Zeile stehen? All dies macht die Extraktionslogik anders. – Kent
Diese Antwort könnte auch zutreffen: https://Stackoverflow.com/a/48022994/2026975 – imriss