Làm cách nào để có được dòng đầu tiên của tệp trong tập lệnh bash?


249

Tôi phải đặt một biến bash dòng đầu tiên của tệp. Tôi đoán đó là với lệnh grep, nhưng nó có cách nào để hạn chế số lượng dòng không?

Câu trả lời:


396

headlấy các dòng đầu tiên từ một tệp và -ntham số có thể được sử dụng để chỉ định số lượng dòng nên được trích xuất:

line=$(head -n 1 filename)

3
Chi phí cao hơn đáng kể so với readcách tiếp cận. $()loại bỏ một lớp con và sử dụng lệnh bên ngoài ( bất kỳ lệnh bên ngoài nào ) có nghĩa là bạn đang gọi execve(), gọi trình liên kết và trình tải (nếu nó sử dụng các thư viện dùng chung, thường là như vậy), v.v.
Charles Duffy

2
Nó thậm chí có thể ngắn hơn:line="$(head -1 FILENAME)"
nikolay

3
Và cũng:line=`head -1 FILENAME`
Shai Alon

Liệu các backticks xung quanh head...mở một subshell như $()vậy?.
Jaime Hablutzel

@JaimeHablutzel Vâng, chúng giống nhau, mặc dù cá nhân tôi thấy rằng $()cú pháp dễ nhìn hơn và giá trị rõ ràng hơn độ căng tuyệt đối. gnu.org/software/bash/manual/html_node/ từ
Joseph Sikorski

61

để đọc dòng đầu tiên bằng cách sử dụng bash, sử dụng readcâu lệnh. ví dụ

read -r firstline<file

firstline sẽ là biến của bạn (Không cần gán cho người khác)


1
@sorin, cat ... | read VARsẽ thất bại trong hầu hết các shell (tất cả ngoại trừ zshtheo như tôi biết) bởi vì mỗi thành phần trong một đường ống sẽ chạy trong các lớp con riêng biệt. Có nghĩa là nó $VARsẽ được đặt trong subshell (nó sẽ không còn tồn tại ngay khi đường ống đã hoàn thành thực thi) chứ không phải trong vỏ gọi. Bạn có thể giải quyết vấn đề này với read VAR <<EOF\n$(cat ...)\nEOF(trong đó mỗi \ndòng là một dòng mới).
zrajm

@sorin, catlà chi phí thuần túy; hiệu quả read -r var <filehơn nhiều so với bất kỳ cách nào cat file | read, ngay cả khi điều sau không thất bại vì những lý do được mô tả trong BashFAQ # 24 .
Charles Duffy

... nếu bạn đang chạy thứ gì đó liên quan nhiều hơn cat, thìread -r var < <(otherprog ...)
Charles Duffy

14

Điều này đủ và lưu trữ dòng đầu tiên filenametrong biến $line:

read -r line < filename

Tôi cũng thích awkđiều này:

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

Để lưu trữ chính dòng, sử dụng var=$(command)cú pháp. Trong trường hợp này , line=$(awk 'NR==1 {print; exit}' file).

Hoặc thậm chí sed:

sed -n '1p' file

Với tương đương line=$(sed -n '1p' file).


Xem một mẫu khi chúng tôi cung cấp readvới seq 10, đó là một chuỗi các số từ 1 đến 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'(hoặc sed -n '1p;q') sẽ bắt chước awklogic của bạn và ngăn việc đọc thêm vào tệp. Bởi vì chúng tôi chỉ muốn dòng đầu tiên, chúng ta có thể lựa chọn gian lận với sed qhoặc awk '1;{exit}'hoặc thậm chí grep -m1 ^(ít mã, cùng một logic cần thiết). (Đây không phải là câu trả lời cho cuộc điều tra downvote.)
Adam Katz

@AdamKatz đó là một cách rất hay, cảm ơn! Tôi tìm thấy một trong những greprất thông minh. Tất nhiên chúng ta cũng có thể nói head -n 1 file.
fedorqui 'SO ngừng làm hại'

Có, head -n1sẽ nhanh hơn (tải nhị phân nhỏ hơn) và readsẽ nhanh nhất (không tải nhị phân, đó là nội dung). Tôi đặc biệt thích grep -m1 --color .khi tôi chỉ in dòng đầu tiên vì nó cũng sẽ tô màu dòng đó, làm cho nó tuyệt vời cho tiêu đề bảng.
Adam Katz

12
line=$(head -1 file)

Sẽ làm việc tốt. (Như câu trả lời trước). Nhưng

line=$(read -r FIRSTLINE < filename)

sẽ nhanh hơn một chút so với readlệnh bash tích hợp.


21
Phương thức thứ hai không hoạt động như được viết, bởi vì readkhông in bất cứ thứ gì (vì vậy, để linetrống) và cũng thực hiện trong một khung con (vì vậy FIRSTLINEđược đặt thành dòng đầu tiên, nhưng chỉ trong dòng con, vì vậy nó không có sẵn sau đó). Giải pháp: chỉ cần sử dụngread -r line <filename
Gordon Davisson

5

Chỉ cần echodanh sách đầu tiên của tệp nguồn của bạn vào tệp mục tiêu của bạn.

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

3
head -n 1 source.txt > target.txtsẽ hoàn thành chính xác như nhau.
YoYo

4

Câu hỏi không hỏi cái nào nhanh nhất, nhưng để thêm vào câu trả lời sed, -n '1p' hoạt động kém vì không gian mẫu vẫn được quét trên các tệp lớn. Vì tò mò tôi thấy rằng 'cái đầu' chiến thắng trong sed một cách hẹp hòi:

# 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.