2016-11-18 4 views
2

Ich muss ~ 5000 Zeilen aus einer Datei mit ~ 300.000 Zeilen auf Bash (OSX) extrahieren.Extrahieren große Liste von Zeilen aus großen Textdatei

Lauf
sed '128082p;128083p;...(4996 numbers)....;159845q;d' file > output 

gibt dem Fehler

sed: 1: "128082p;128083p;128084p ...": command expected 

dem selben Befehl funktioniert, wenn ich versuche, nur 10 Zeilen zu extrahieren. Dagegen läuft

for i in `cat line_file`; do sed -n "$ip" file; done >> output 

erstellt eine Datei, die mehr als ~ 5000 Zeilen lang ist. Was ist der richtige Befehl in beiden Fällen?

Edit: das ist nicht eine Reihe von Zahlen.

+0

@Sundeep Die Liste der Nummern scheint nicht ein Bereich zu sein '128082 + 5000 = 133082' ist nicht die Nummer, die der Benutzer gepostet hat:' 159845'. – sorontar

+0

@sorontar, true .. Frage ist unklar .. aber ich denke, OP will eine Reichweite (was auch immer das sein könnte) – Sundeep

+0

warum haben Sie die nachstehende '; d'? Und was ist mit 'sed -n' 128082,133082p; 133083q 'Datei> out'? Viel Glück. – shellter

Antwort

3

Tipp des Hutes zu Jonathan Leffler für seine Hilfe.

Es sieht aus wie BSD sed als auf macOS verwendet (Stand macOS 10.12.1) eine harte Grenze für die Größe der einzelnen Linie eines Skripts, die an sie übergeben werden können: 2048 Bytes.

Wenn er als Befehlszeilenargument geben (implizit als ersten Operanden, oder explizit über -e Optionen), werden Skripte typischerweise als einzelne Zeile übergeben, wie Sie.

Wenn diese einzelne Zeile zu lang wird, wird sie leider blind abgeschnitten, was normalerweise zu einem scheinbar zufälligen Syntaxfehler führt, wie der, den Sie gesehen haben.

Es gibt zwei Umgehungen:

  • Stellen Sie sicher, dass Ihr Skript nur kurz genug Linien durch die Trennung Befehle mit \n (Zeilenumbrüche) statt ; und/oder teilen Sie Ihre Skript über mehrere enthält -e Optionen (was umständlich ist).

  • das gesamte Skript Geben Sie über eine Datei, die -f Option verwenden, wobei in diesem Fall alle Befehle müssen mit \n statt ; ohnehin getrennt werden.
    In dem unwahrscheinlichen Fall, dass Ihr Skript zu lang ist, um auf eine einzige Befehlszeile zu passen (ein Grenzwert von System - siehe unten), ist -f Ihre einzige Option.


Hier ist ein Beispiel für eine Befehlszeilenskript, das zu lang ist:

$ sed -n "$(printf '%sp;' {1..432})" <<<'line 1' 
sed: 1: "1p;2p;3p;4p;5p;6p;7p;8p ...": command expected # !! ERROR 

Auch wenn das Skript syntaktisch korrekt ist, seine ein Schneiden und nur bei 2048 Bytes Blättern Leitung aus es ist falsch, was zu dem scheinbar zufälligen command expected Fehler führt.

In diesem Fall arbeiten rund um die Begrenzung ist einfach: durch ; mit \n, die einzelnen Leitungen werden kurz genug, um zu ersetzen:

$ sed -n "$(printf '%sp\n' {1..432})" <<<'line 1' 
line 1 # OK 

Da Sie bereits eine Datei von Zeilennummern haben - line_file - Sie kann einen Hilfssed Befehl verwenden, um Ihre \n -separated Skript aus, es zu schaffen:

$ sed -n "$(sed 's/$/p/' line_file)" file > output 

Hier ist, wie das Problem über ein Skript zu lösen Datei über -f geben, in der die Befehle \n sind -separated das Problem behebt:

$ printf '%sp\n' {1..432} > script.sed # Create script file with \n-separated commands. 
$ sed -n -f "script.sed" <<<'line 1' # Pass script file via -f 
line 1 # OK 

Hinweis: Die Verwendung eines Verfahrens Substitution (sed -n -f <(printf ...) ...) als Eine Ad-hoc-Skriptdatei funktioniert unerklärlicherweise nicht.

Beachten Sie auch, dass die insgesamt max. Länge einer Befehlszeile zum Aufrufen eines externen Dienstprogramms wie sed auf MacOS (ab 10.12) ist 262144 (256 KB; bestimmt mit getconf ARG_MAX), und in der Praxis ist die Grenze niedriger, weil die Größe des Umgebungsvariablen Block a spielt Rolle. Wenn Sie dieses Limit jedoch erreichen, erhalten Sie eine hilfreichere Fehlermeldung: Argument list too long.

+2

Ihr Größenlimit ist, was ich vermutete, wusste aber nicht, da es auf kleinere Befehle funktionierte . Der Befehl "sed -n" $ (sed 's/$/p /' line_file) "Datei> Ausgabe" funktionierte und in weniger als einer Minute. 1+ auch für sehr hilfreiche Erklärungen. – aish1249

Verwandte Themen