Wie bekomme ich die erste Zeile einer Datei in einem Bash-Skript?

249

Ich muss die erste Zeile einer Datei in eine Bash-Variable einfügen. Ich denke, es ist mit dem Befehl grep, aber ist es eine Möglichkeit, die Anzahl der Zeilen zu beschränken?

Neuquino
quelle

Antworten:

396

headNimmt die ersten Zeilen aus einer Datei und der -nParameter kann verwendet werden, um anzugeben, wie viele Zeilen extrahiert werden sollen:

line=$(head -n 1 filename)
etw
quelle
3
Deutlich mehr Aufwand als der readAnsatz. $()Wenn Sie eine Subshell abschalten und einen externen Befehl (einen beliebigen externen Befehl) verwenden execve(), rufen Sie den Linker und den Loader auf (wenn gemeinsam genutzte Bibliotheken verwendet werden, was normalerweise der Fall ist) usw.
Charles Duffy
2
Es könnte noch kürzer sein:line="$(head -1 FILENAME)"
Nikolay
3
Und auch:line=`head -1 FILENAME`
Shai Alon
Öffnen die Backticks um das head...Open eine Subshell wie $()?
Jaime Hablutzel
@JaimeHablutzel Ja, sie sind dasselbe, obwohl ich persönlich finde, dass die $()Syntax leichter zu erkennen ist und Klarheit über absolute Knappheit steht. gnu.org/software/bash/manual/html_node/…
Joseph Sikorski
61

Verwenden Sie die readAnweisung , um die erste Zeile mit bash zu lesen . z.B

read -r firstline<file

firstline wird Ihre Variable sein (keine Notwendigkeit, einem anderen zuzuweisen)

Ghostdog74
quelle
1
@sorin, cat ... | read VARwird in den meisten Shells fehlschlagen (alle außer zshsoweit ich weiß), da jede der Komponenten in einem Rohr in separaten Subshells ausgeführt wird. $VARDies bedeutet, dass dies in der Subshell (die nicht mehr vorhanden ist, sobald die Ausführung der Pipeline abgeschlossen ist) und nicht in der aufrufenden Shell festgelegt wird. Sie können dies umgehen mit read VAR <<EOF\n$(cat ...)\nEOF(wobei jede \neine neue Zeile ist).
Zrajm
@sorin, catist reiner Overhead; viel effizienter read -r var <fileals cat file | readsowieso, auch wenn letzteres aus den in BashFAQ # 24 beschriebenen Gründen nicht fehlgeschlagen ist .
Charles Duffy
... wenn Sie etwas mehr involvieren als cat, dannread -r var < <(otherprog ...)
Charles Duffy
14

Dies reicht aus und speichert die erste Zeile von filenamein der Variablen $line:

read -r line < filename

Ich mag auch awkdafür:

awk 'NR==1 {print; exit}' file

Verwenden Sie die var=$(command)Syntax, um die Zeile selbst zu speichern . In diesem Fall line=$(awk 'NR==1 {print; exit}' file).

Oder sogar sed:

sed -n '1p' file

Mit dem Äquivalent line=$(sed -n '1p' file).


Sehen Sie sich ein Beispiel an, wenn wir das readmit seq 10einer Zahlenfolge von 1 bis 10 füttern :

$ read -r line < <(seq 10) 
$ echo "$line"
1

$ line=$(awk 'NR==1 {print; exit}' <(seq 10))
$ echo "$line"
1
fedorqui 'SO hör auf zu schaden'
quelle
1
sed '1!d;q'(oder sed -n '1p;q') ahmt Ihre awkLogik nach und verhindert, dass Sie weiter in die Datei lesen. Da wir nur die erste Zeile wollen, können wir alternativ mit sed qoder awk '1;{exit}'oder sogar betrügen grep -m1 ^(weniger Code, dieselbe wesentliche Logik). (Dies ist keine Antwort auf die Downvote-Anfrage.)
Adam Katz
@AdamKatz das ist eine sehr schöne Reihe von Möglichkeiten, danke! Ich finde den mit grepsehr klug. Das können wir natürlich auch sagen head -n 1 file.
Fedorqui 'SO hör auf,'
Ja, head -n1wird schneller sein (kleinere Binärdatei zum Laden) und readwird am schnellsten sein (keine Binärdatei zum Laden, das ist eingebaut). Ich mag es besonders, grep -m1 --color .wenn ich nur die erste Zeile drucke, weil sie auch die Zeile färbt und sich hervorragend für Tabellenüberschriften eignet.
Adam Katz
12
line=$(head -1 file)

Wird gut funktionieren. (Wie vorherige Antwort). Aber

line=$(read -r FIRSTLINE < filename)

wird geringfügig schneller sein als readein eingebauter Bash-Befehl.

Jackbot
quelle
21
Die zweite Methode funktioniert nicht wie geschrieben, weil readsie nichts druckt (wird also lineleer) und auch in einer Unterschale ausgeführt (wird also FIRSTLINEauf die erste Zeile gesetzt, aber nur in der Unterschale, sodass sie danach nicht verfügbar ist). Lösung: verwenden Sie einfachread -r line <filename
Gordon Davisson
5

Nur echodie erste Liste Ihrer Quelldatei in Ihre Zieldatei.

echo $(head -n 1 source.txt) > target.txt
openwonk
quelle
3
Wofür head -n 1 source.txt > target.txtwird genau das gleiche erreichen.
YoYo
4

Bei der Frage wurde nicht gefragt, welche am schnellsten ist, aber um die sed-Antwort zu ergänzen, ist -n '1p' schlecht, da der Musterbereich immer noch in großen Dateien gescannt wird. Aus Neugier fand ich heraus, dass 'Kopf' nur knapp über Sed gewinnt:

# best:
head -n1 $bigfile >/dev/null

# a bit slower than head (I saw about 10% difference):
sed '1q' $bigfile >/dev/null

# VERY slow:
sed -n '1p' $bigfile >/dev/null
Neil McGill
quelle