676 Stimmen

Wie kann ich einen bestimmten Bereich von Zeilen aus einer Textdatei unter Unix extrahieren?

Ich habe einen SQL-Dump mit ~23000 Zeilen, der Daten aus mehreren Datenbanken enthält. Ich muss einen bestimmten Abschnitt dieser Datei (d. h. die Daten für eine einzelne Datenbank) extrahieren und in eine neue Datei einfügen. Ich kenne sowohl die Anfangs- als auch die Endzeilennummer der gewünschten Daten.

Kennt jemand einen Unix-Befehl (oder eine Reihe von Befehlen), um alle Zeilen aus einer Datei zwischen z.B. Zeile 16224 und 16482 zu extrahieren und sie dann in eine neue Datei umzuleiten?

1voto

DrNerdfighter Punkte 79

Ich habe ein kleines Bash-Skript geschrieben, das Sie von Ihrer Kommandozeile aus ausführen können, sofern Sie Ihr PATH-Verzeichnis aktualisieren (oder Sie können es in einem Verzeichnis ablegen, das bereits im PATH enthalten ist).

Verwendung: $ pinch filename start-line end-line

#!/bin/bash
# Display line number ranges of a file to the terminal.
# Usage: $ pinch filename start-line end-line
# By Evan J. Coon

FILENAME=$1
START=$2
END=$3

ERROR="[PINCH ERROR]"

# Check that the number of arguments is 3
if [ $# -lt 3 ]; then
    echo "$ERROR Need three arguments: Filename Start-line End-line"
    exit 1
fi

# Check that the file exists.
if [ ! -f "$FILENAME" ]; then
    echo -e "$ERROR File does not exist. \n\t$FILENAME"
    exit 1
fi

# Check that start-line is not greater than end-line
if [ "$START" -gt "$END" ]; then
    echo -e "$ERROR Start line is greater than End line."
    exit 1
fi

# Check that start-line is positive.
if [ "$START" -lt 0 ]; then
    echo -e "$ERROR Start line is less than 0."
    exit 1
fi

# Check that end-line is positive.
if [ "$END" -lt 0 ]; then
    echo -e "$ERROR End line is less than 0."
    exit 1
fi

NUMOFLINES=$(wc -l < "$FILENAME")

# Check that end-line is not greater than the number of lines in the file.
if [ "$END" -gt "$NUMOFLINES" ]; then
    echo -e "$ERROR End line is greater than number of lines in file."
    exit 1
fi

# The distance from the end of the file to end-line
ENDDIFF=$(( NUMOFLINES - END ))

# For larger files, this will run more quickly. If the distance from the
# end of the file to the end-line is less than the distance from the
# start of the file to the start-line, then start pinching from the
# bottom as opposed to the top.
if [ "$START" -lt "$ENDDIFF" ]; then
    < "$FILENAME" head -n $END | tail -n +$START
else
    < "$FILENAME" tail -n +$START | head -n $(( END-START+1 ))
fi

# Success
exit 0

1voto

potong Punkte 51035

Dies könnte für Sie funktionieren (GNU sed):

sed -ne '16224,16482w newfile' -e '16482q' file

oder die Vorteile der Bash nutzen:

sed -n $'16224,16482w newfile\n16482q' file

1voto

Kemin Zhou Punkte 5151

Da wir über das Extrahieren von Textzeilen aus einer Textdatei sprechen, werde ich einen speziellen Fall beschreiben, in dem Sie alle Zeilen extrahieren möchten, die einem bestimmten Muster entsprechen.

myfile content:
=====================
line1 not needed
line2 also discarded
[Data]
first data line
second data line
=====================
sed -n '/Data/,$p' myfile

Druckt die [Data]-Zeile und den Rest. Wenn Sie den Text aus Zeile 1 in das Muster übernehmen wollen, geben Sie ein: sed -n '1,/Data/p' myfile. Wenn Sie außerdem zwei Muster kennen (die in Ihrem Text besser eindeutig sein sollten), können sowohl die Anfangs- als auch die Endzeile des Bereichs mit Übereinstimmungen angegeben werden.

sed -n '/BEGIN_MARK/,/END_MARK/p' myfile

0voto

ThinkBonobo Punkte 13628

Das -n in den akzeptierten Antworten funktioniert. Hier ist eine andere Möglichkeit, falls Sie dazu neigen.

cat $filename | sed "${linenum}p;d";

Damit wird Folgendes erreicht:

  1. den Inhalt einer Datei über die Pipeline einspeisen (oder den Text nach Belieben einfügen).
  2. sed wählt die angegebene Zeile aus und gibt sie aus
  3. d ist erforderlich, um Zeilen zu löschen, da sed sonst davon ausgeht, dass alle Zeilen gedruckt werden. d.h. ohne d werden alle Zeilen gedruckt, die durch die ausgewählte Zeile doppelt gedruckt werden, da der Teil ${linenum}p darum bittet, dass sie gedruckt werden. Ich bin mir ziemlich sicher, dass das -n hier im Grunde das Gleiche tut wie das d.

0voto

Kahiga Punkte 33

Ich habe nach einer Antwort auf diese Frage gesucht, aber ich musste schließlich meinen eigenen Code schreiben, der funktioniert hat. Keine der obigen Antworten war zufriedenstellend. Nehmen wir an, Sie haben eine sehr große Datei mit bestimmten Zeilennummern, die Sie ausdrucken möchten, aber die Nummern sind nicht in der richtigen Reihenfolge. Sie können wie folgt vorgehen:

Meine relativ große Datei for letter in {a..k} ; do echo $letter; done | cat -n > myfile.txt

 1  a
 2  b
 3  c
 4  d
 5  e
 6  f
 7  g
 8  h
 9  i
10  j
11  k

Ich möchte bestimmte Zeilennummern: shuf -i 1-11 -n 4 > line_numbers_I_want.txt

 10
 11
 4
 9

Um diese Zeilennummern zu drucken, gehen Sie wie folgt vor. awk '{system("head myfile.txt -n " $0 " | tail -n 1")}' line_numbers_I_want.txt

Die obige Funktion besteht darin, die Zeile n zu überschreiben und dann die letzte Zeile mit tail zu übernehmen

Wenn Sie die Zeilennummern in der richtigen Reihenfolge haben wollen, sortieren Sie zuerst (mit -n numeric sort) und holen Sie dann die Zeilen.

cat line_numbers_I_want.txt | sort -n | awk '{system("head myfile.txt -n " $0 " | tail -n 1")}'

 4  d
 9  i
10  j
11  k

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X