Ich versuche, eine bestimmte Zeile aus einer Textdatei zu erhalten.
Bisher habe ich online nur Dinge wie sed gesehen (ich kann nur sh-not bash oder sed oder ähnliches verwenden). Ich muss dies nur mit einem einfachen Shell-Skript tun.
cat file | while read line
do
#do something
done
Ich weiß, wie man wie oben gezeigt durch Zeilen iteriert, aber was ist, wenn ich nur den Inhalt einer bestimmten Zeile abrufen muss
cat
okay, abersed
nicht? Das macht keinen Sinn.cat
. Aw ... süßcat
!Antworten:
sed:
awk:
quelle
5!d
bedeutet, alle Zeilen außer 5 zu löschen. Shell var ist möglich, Sie benötigen doppelte Anführungszeichen.sed -n 5p
Dies scheint für Neulinge logischer zu sein, da-n
dies "standardmäßig keine Ausgabe" bedeutet undp
für "Drucken" steht und das Löschen möglicherweise nicht verwirrend erwähnt wird (wenn Leute von Dateien sprechen, neigt das Löschen von Zeilen dazu etwas anderes bedeuten).-n '5p'
funktioniert auch für dieses Problem. Der Unterschied besteht darin, dass5!d
Sie hinzufügen können-i
, um die Änderung zurück in die Datei zu schreiben. jedoch mit-n 5p
Ihnen zu haben ,sed -n '5p' f > f2&& mv f2 f
wieder, für diese Frage, ich bin einverstanden mit Ihrer Meinung.Angenommen, es
line
handelt sich um eine Variable, die Ihre erforderliche Zeilennummer enthält. Wenn Siehead
und verwenden könnentail
, ist dies ganz einfach:Wenn nicht, sollte dies funktionieren:
quelle
-eq
Vergleich gilt für Ganzzahlen, daher wird eine Zeilennummer und kein Zeileninhalt ($line
) benötigt. Dies muss behoben werden, indem z. B.want=5
vor der Schleife definiert und dann der-eq
Vergleich aktiviert wird$want
. [bewegt von einer abgelehnten Bearbeitung]Sie könnten verwenden
sed -n 5p file
.Sie können auch eine Reichweite erhalten, z
sed -n 5,10p file
.quelle
Die beste Leistung Methode
Weil
sed
nach dem 5. keine Zeilen mehr gelesen werdenUpdate Experiment von Herrn Roger Dueck
quelle
sed -n 5q
sed
nach dem 5. keine Zeilen mehr gelesen werden.sed -n 1p /usr/share/dict/words
undsed '1q;d' /usr/share/dict/words
dentime
Befehl verglichen und verwendet . Der erste dauerte 0,043 Sekunden, der zweite nur 0,002 Sekunden. Die Verwendung von 'q' ist also definitiv eine Leistungsverbesserung!Wenn Sie beispielsweise die Zeilen 10 bis 20 einer Datei abrufen möchten, können Sie jede dieser beiden Methoden verwenden:
oder
p
im obigen Befehl steht für Drucken.Folgendes werden Sie sehen:
quelle
Die Standardmethode für diese Art von Dingen ist die Verwendung externer Tools. Es ist absurd, die Verwendung externer Tools beim Schreiben eines Shell-Skripts nicht zuzulassen. Wenn Sie jedoch keine externen Tools verwenden möchten, können Sie Zeile 5 drucken mit:
Beachten Sie, dass dadurch die logische Zeile 5 gedruckt wird. Wenn also
input-file
Zeilenfortsetzungen enthalten sind, werden diese als einzelne Zeile gezählt. Sie können dieses Verhalten ändern, indem Sie-r
dem Lesebefehl hinzufügen . (Welches ist wahrscheinlich das gewünschte Verhalten.)quelle
$((++i))
scheint ein Bashismus zu sein; Wenn das OP nur externe Tools verwenden kann, würde ich nicht davon ausgehen, dass sie Zugriff auf mehr als eine Ebene haben/bin/sh
++
Inkremente ist jedoch ausdrücklich als optional gekennzeichnet).$((i+=1))
in Dash funktioniert auch.$(($i+1))
ist die einfache Problemumgehung, an die ich gedacht habe.Parallel zur Antwort von William Pursell gibt es hier ein einfaches Konstrukt, das auch in der ursprünglichen v7 Bourne-Shell funktionieren sollte (und somit auch dort, wo Bash nicht verfügbar ist).
Beachten Sie auch die Optimierung,
break
um aus der Schleife herauszukommen, wenn wir die gesuchte Linie erhalten haben.quelle
Ich mochte keine der Antworten besonders.
Hier ist, wie ich es gemacht habe.
quelle
Einfach mit Perl! Wenn Sie Zeile 1, 3 und 5 aus einer Datei abrufen möchten, sagen Sie / etc / passwd:
quelle
seq 5 | perl -ne 'print if $. ~~ [1, 4, 5]'
Aber Smartmatch ist experimentell und es wird von der Verwendung abgeratenquelle
sed -n 5p
, was natürlich immer noch auf so etwas wie optimiert werden kannsed -n '5!d;p;q'