Jak uzyskać pierwszą linię pliku w skrypcie bash?


249

Muszę wstawić zmienną bash do pierwszego wiersza pliku. Wydaje mi się, że dzieje się tak z poleceniem grep, ale czy można ograniczyć liczbę linii?

Odpowiedzi:


396

headpobiera pierwsze wiersze z pliku, a -nparametru można użyć do określenia, ile wierszy należy wyodrębnić:

line=$(head -n 1 filename)

3
Znacznie więcej kosztów ogólnych niż readpodejście. $()rozwidla podpowłokę, a użycie polecenia zewnętrznego ( dowolnego polecenia zewnętrznego) oznacza, że ​​dzwonisz execve(), wywołujesz linker i moduł ładujący (jeśli korzysta z bibliotek współdzielonych, co zwykle ma miejsce), itp.
Charles Duffy

2
Może być jeszcze krótszy:line="$(head -1 FILENAME)"
Nikolay

3
A także:line=`head -1 FILENAME`
Shai Alon

Czy backtyki wokół head...otwartej podpowłoki, podobnie $()jak ?.
Jaime Hablutzel

@JaimeHablutzel Tak, są to te same rzeczy, chociaż osobiście uważam, że $()składnia jest łatwiejsza do zauważenia i cenię przejrzystość ponad absolutną zwięzłość. gnu.org/software/bash/manual/html_node/…
Joseph Sikorski

61

aby przeczytać pierwszą linię za pomocą bash, użyj readinstrukcji. na przykład

read -r firstline<file

firstline będzie twoją zmienną (nie musisz przypisywać do innej)


1
@sorin, cat ... | read VARzawiedzie w większości powłok (wszystkie z wyjątkiem, zsho ile wiem), ponieważ każdy ze składników potoku będzie działał w osobnych podpowłokach. Oznacza to, że $VARzostanie ustawione w podpowłoce (która przestanie istnieć, gdy tylko potok zakończy działanie), a nie w powłoce wywołującej. Możesz to obejść za pomocą read VAR <<EOF\n$(cat ...)\nEOF(gdzie każdy \njest nowym wierszem).
zrajm

@sorin, catto czysty narzut; znacznie bardziej wydajne read -r var <fileniż cat file | readjakikolwiek, nawet jeśli ten ostatni nie zawiódł z powodów opisanych w BashFAQ # 24 .
Charles Duffy,

... jeśli prowadzisz coś bardziej zaangażowanego niż cat, toread -r var < <(otherprog ...)
Charles Duffy

14

To wystarcza i przechowuje pierwszy wiersz filenamezmiennej $line:

read -r line < filename

Lubię też awkza to:

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

Aby zapisać samą linię, użyj var=$(command)składni. W tym wypadku line=$(awk 'NR==1 {print; exit}' file).

Lub nawet sed:

sed -n '1p' file

Z ekwiwalentem line=$(sed -n '1p' file).


Patrz próbki kiedy paszy readz seq 10, to sekwencja liczb od 1 do 10:

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

$ line=$(awk 'NR==1 {print; exit}' <(seq 10))
$ echo "$line"
1

1
sed '1!d;q'(lub sed -n '1p;q') naśladuje twoją awklogikę i uniemożliwi dalsze wczytywanie do pliku. Ponieważ chcemy tylko pierwszy wiersz, możemy oszukać alternatywnie z sed qlub awk '1;{exit}'nawet grep -m1 ^(mniej kodu, tak samo niezbędna logika). (To nie jest odpowiedź na negatywne zapytanie).
Adam Katz

@AdamKatz to bardzo fajny zestaw sposobów, dzięki! Uważam ten za grepbardzo mądry. Oczywiście możemy również powiedzieć head -n 1 file.
fedorqui „SO przestań krzywdzić”

Tak, head -n1będzie szybszy (mniejszy plik binarny do załadowania) i readbędzie najszybszy (brak pliku binarnego do załadowania, to wbudowane). Szczególnie podoba grep -m1 --color .mi się, gdy drukuję tylko pierwszą linię, ponieważ również pokoloruje linię, dzięki czemu świetnie nadaje się do nagłówków tabel.
Adam Katz

12
line=$(head -1 file)

Będzie działać dobrze. (Jak poprzednia odpowiedź). Ale

line=$(read -r FIRSTLINE < filename)

będzie nieznacznie szybszy, podobnie jak readwbudowane polecenie bash.


21
Druga metoda nie działa tak, jak napisano, ponieważ readnic nie drukuje (więc linekończy się pusta), a także wykonuje się w podpowłoce ( FIRSTLINEustawia się w pierwszej linii, ale tylko w podpowłoce, więc nie jest dostępna później). Rozwiązanie: po prostu użyjread -r line <filename
Gordon Davisson

5

Tylko echopierwsza lista pliku źródłowego do pliku docelowego.

echo $(head -n 1 source.txt) > target.txt

3
Do czego head -n 1 source.txt > target.txtosiągnie dokładnie to samo.
YoYo,

4

Pytanie nie zadawało, które jest najszybsze, ale aby dodać do odpowiedzi sed, -n „1p” ma niską wydajność, ponieważ przestrzeń wzorców jest nadal skanowana na dużych plikach. Z ciekawości odkryłem, że „głowa” wygrywa nad sedem wąsko:

# 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.