Bagaimana cara mendapatkan baris pertama file dalam skrip bash?

249

Saya harus memasukkan variabel bash pada baris pertama file. Saya kira itu dengan perintah grep, tetapi apakah ada cara untuk membatasi jumlah baris?

Neuquino
sumber

Jawaban:

396

headmengambil baris pertama dari file, dan -nparameter dapat digunakan untuk menentukan berapa banyak baris yang harus diekstraksi:

line=$(head -n 1 filename)
sth
sumber
3
Secara signifikan lebih banyak overhead daripada readpendekatan. $()memotong subkulit, dan menggunakan perintah eksternal (perintah eksternal apa pun ) berarti Anda memanggil execve(), memanggil tautan dan pemuat (jika menggunakan pustaka bersama, yang biasanya merupakan kasus), dll.
Charles Duffy
2
Bisa jadi lebih pendek:line="$(head -1 FILENAME)"
nikolay
3
Dan juga:line=`head -1 FILENAME`
Shai Alon
Apakah backticks di sekitar head...membuka subkulit seperti $()halnya?
Jaime Hablutzel
@JaimeHablutzel Ya, mereka adalah hal yang sama, meskipun secara pribadi saya menemukan bahwa $()sintaksis lebih mudah dilihat, dan menghargai kejelasan atas kepastian mutlak. gnu.org/software/bash/manual/html_node/…
Joseph Sikorski
61

untuk membaca baris pertama menggunakan bash, gunakan readpernyataan. misalnya

read -r firstline<file

firstline akan menjadi variabel Anda (Tidak perlu menetapkan ke yang lain)

ghostdog74
sumber
1
@sorin, cat ... | read VARakan gagal di sebagian besar shell (semua kecuali zshsejauh yang saya tahu) karena masing-masing komponen dalam pipa akan berjalan di subkulit yang terpisah. Arti yang $VARakan diatur dalam subkulit (yang tidak ada segera setelah pipa selesai dieksekusi) daripada di shell yang memohon. Anda dapat menyiasati ini dengan read VAR <<EOF\n$(cat ...)\nEOF(di mana masing \n- masing adalah baris baru).
zrajm
@sorin, catadalah overhead murni; jauh lebih efisien read -r var <filedaripada cat file | readbagaimana pun, bahkan jika yang terakhir tidak gagal karena alasan yang dijelaskan dalam BashFAQ # 24 .
Charles Duffy
... jika Anda menjalankan sesuatu yang lebih terlibat daripada cat, makaread -r var < <(otherprog ...)
Charles Duffy
14

Ini mencukupi dan menyimpan baris pertama filenamedalam variabel $line:

read -r line < filename

Saya juga suka awkuntuk ini:

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

Untuk menyimpan garis itu sendiri, gunakan var=$(command)sintaksisnya. Dalam hal ini line=$(awk 'NR==1 {print; exit}' file),.

Atau bahkan sed:

sed -n '1p' file

Dengan yang setara line=$(sed -n '1p' file).


Lihat sampel saat kami memberi makan readdengan seq 10, yaitu, urutan angka dari 1 hingga 10:

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

$ line=$(awk 'NR==1 {print; exit}' <(seq 10))
$ echo "$line"
1
fedorqui 'SO berhenti merugikan'
sumber
1
sed '1!d;q'(atau sed -n '1p;q') akan meniru awklogika Anda dan mencegah pembacaan lebih jauh ke dalam file. Karena kami hanya ingin baris pertama, kita alternatif bisa menipu dengan sed qatau awk '1;{exit}'atau bahkan grep -m1 ^(kode kurang, logika penting yang sama). (Ini bukan balasan untuk pertanyaan downvote.)
Adam Katz
@AdamKatz itu seperangkat cara yang sangat bagus, terima kasih! Saya menemukan satu dengan grepsangat cerdas. Tentu saja kita juga bisa mengatakannya head -n 1 file.
fedorqui 'SO berhenti merugikan'
Ya, head -n1akan lebih cepat (biner lebih kecil untuk dimuat) dan readakan tercepat (tidak ada biner untuk dimuat, itu bawaan). Saya terutama suka grep -m1 --color .ketika saya hanya mencetak baris pertama karena akan mewarnai garis juga, membuatnya bagus untuk judul tabel.
Adam Katz
12
line=$(head -1 file)

Akan bekerja dengan baik. (Seperti jawaban sebelumnya). Tapi

line=$(read -r FIRSTLINE < filename)

akan sedikit lebih cepat seperti readperintah bash bawaan.

jackbot
sumber
21
Metode kedua tidak bekerja seperti yang tertulis, karena readtidak mencetak apa pun (jadi lineberakhir kosong), dan juga dijalankan dalam subkulit (jadi FIRSTLINEdiatur ke baris pertama, tetapi hanya dalam subkulit, sehingga tidak tersedia setelahnya). Solusi: cukup gunakanread -r line <filename
Gordon Davisson
5

Hanya echodaftar pertama file sumber Anda ke file target Anda.

echo $(head -n 1 source.txt) > target.txt
openwonk
sumber
3
Untuk yang head -n 1 source.txt > target.txtakan mencapai hal yang persis sama.
YoYo
4

Pertanyaannya tidak menanyakan yang tercepat, tetapi untuk menambah jawaban sed, -n '1p' berkinerja buruk karena ruang pola masih dipindai pada file besar. Karena penasaran saya menemukan bahwa 'kepala' menang atas sed sempit:

# 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
sumber