Làm thế nào để chỉ in nội dung tệp nếu dòng đầu tiên khớp với một mẫu nhất định?


11

Tôi đang viết một kịch bản, tôi muốn kiểm tra xem dòng đầu tiên của tệp có khớp với một mẫu nhất định không và nếu có thì in ra tệp. Làm thế nào tôi có thể đạt được điều này?

Làm thế nào để tôi kiểm tra mẫu? Có cách nào để kiểm tra mẫu và dựa trên đầu ra làm gì không ..

EDIT: Vui lòng xem câu hỏi này: /programming/5536018/how-to-get-match-regex-potype-USE-awk-from-file

Tôi muốn một cái gì đó như thế này, nhưng không ai trong số họ làm việc cho tôi. Về cơ bản tôi muốn kiểm tra xem dòng đầu tiên có khớp với mẫu regex hay không và dựa vào đó in các dòng của tệp.


1
Sản lượng bạn mong đợi là gì? Mẫu bạn đang tìm kiếm là gì? Bạn đã thử những gì cho đến nay?
tachomi

@tachomi chỉnh sửa xin vui lòng xem
Mathew

Câu trả lời:


17

Bạn có thể làm điều đó với ed:

ed -s infile <<\IN 2>/dev/null
1s/PATTERN/&/
,p
q
IN

thủ thuật ở đây là cố gắng thay thế PATTERNtrên 1stphù hợp với bản thân. edsẽ báo lỗi nếu không thể tìm thấy mẫu đã chỉ định vì vậy ,p(in toàn bộ tệp) sẽ chỉ được thực thi nếu 1s/PATTERN/&/thành công.

Hoặc với sed:

sed -n '1{
/PATTERN/!q
}
p' infile

quits này nếu dòng đầu tiên không ( !) khớp PATTERN, nếu không nó sẽ pgợi ý tất cả các dòng.
Hoặc, như Toby Speight đã chỉ ra , với GNU sed:

sed '1{/PATTERN/!Q}' infile

Qgiống như qnhưng nó không in không gian mẫu.


Bạn có thể Qthay vì qcho GNU sed, hoặc dtrước đó q(di động) để không yêu cầu -ncờ và plệnh: sed '1{/PATTERN/!Q}' infilehoặc sed -e '1{' -e '/PATTERN/!{' -e 'd' -e 'q' -e '}' -e '}' infile, tương ứng.
Toby Speight

dkhởi động lại chu trình lệnh Luôn luôn bắt tôi! : - |
Toby Speight

Với GNU sed, sedlệnh đầu tiên phàn nàn sed: -e expression #1, char 10: extra characters after command(vì p), nhưng các đề xuất edcuối cùng sedhoạt động tốt.
Skippy le Grand Gourou

Lưu ý: Các giải pháp được cung cấp bởi câu trả lời này có giá trị, hơn các câu trả lời khác, rằng chúng có thể được áp dụng trên một đường ống.
Skippy le Grand Gourou

1
@SkippyleGrandGourou - bạn đã thử biến nó thành một lớp lót mà không tách các lệnh bằng dấu chấm phẩy - đây là cách thích hợp để thực hiệnsed -n '1{/PATTERN/!q};p'
don_crissti

15

Với rương công cụ POSIX:

{ head -n 1 | grep pattern && cat; } <file

1
{đôi} <ngọt ngào.
mikeerv

@mikeerv: Tôi dự định sử dụng nó để ngăn người mới khỏi nhầm lẫn, nhưng Stephane chỉnh sửa thì rõ ràng hơn.
cuonglm

8
 awk '/pattern/{print FILENAME}; {nextfile}' ./*.txt

sẽ in tên của các txttệp không bị ẩn trong thư mục hiện tại có dòng đầu tiên khớp với biểu thức chính quy mở rộng patternvới cácawknextfile tệp thực hiện hỗ trợ .

Nếu thay vì in tên tệp, bạn muốn in toàn bộ nội dung tệp, bạn có thể thực hiện:

 awk 'FNR == 1 && ! /pattern/ {nextfile}; {print}' ./*.txt

Điều đó hiệu quả ở chỗ nó chỉ chạy một lệnh, nhưng awkkhông phải là lệnh hiệu quả nhất để loại bỏ nội dung của tệp, với các tệp lớn, bạn có thể có được hiệu suất tốt hơn bằng cách thực hiện một số thứ như:

 awk '/pattern/{printf "%s\0", FILENAME}; {nextfile}' ./*.txt |
   xargs -r0 cat

Đó là, chỉ sử dụng awkđể in danh sách các tệp khớp (được phân cách bằng 0) và dựa vào catđể kết xuất nội dung của chúng.


6

Nếu bạn đang viết một kịch bản shell, bạn có thể như vậy

for file in ./*; do head -n 1 "$file" | grep -q 'PATTERN' && cat "$file"; done

Hoặc, trong Perl:

perl -Tlne '$f = /PATTERN/ if $. == 1; print if $f; $. = 0 if eof' ./*

@ Stéphane Chazelas: Có lẽ close ARGVlà thành ngữ nhiều hơn là gán cho $..
cuonglm

@terdon Bản thân bạn trông giống như mã golf, tất cả trong một dòng, không có dấu ngoặc quanh các tên biến và không khuyến khích cấu trúc sạch. Và bạn đã có một ký hiệu đô la bị thiếu khi tôi đăng, đó không phải là cách để dạy bash. Tôi cho rằng những yếu tố đó đến từ nền tảng perl mà bạn dường như cũng có, vì vậy bạn sẽ được tha thứ! ;)

@guest xin chào và chào mừng đến với trang web! Tôi đã chuyển đổi câu trả lời của bạn thành một nhận xét vì câu trả lời chỉ nên được đăng nếu họ đang trả lời câu hỏi thực tế. Đây không phải là một diễn đàn theo nghĩa cổ điển và chúng tôi chỉ muốn hỏi đáp thuần túy ở đây. Bạn có thể muốn xem trung tâm trợ giúp hoặc tham quan để hiểu rõ hơn về trang web. Điều đó nói rằng, nền tảng của tôi thực sự là về sinh học nên có, mã của tôi không được sạch :) Tuy nhiên, tôi không thấy dấu ngoặc sẽ giúp gì ở đây, các trích dẫn đã bảo vệ biến. Điều gì sẽ phá vỡ điều này mà ngoặc sẽ bảo vệ?
terdon

@guest ah, xin lỗi, quên bạn không thể bình luận. Hãy đến và giải thích trong trò chuyện , tôi chắc chắn mình có thể học được điều gì đó.
terdon

5

Oldschool, chỉ cần dịch câu của bạn thành các lệnh tiêu chuẩn:

for file in *; do
    if head -n 1 "${file}" | grep -q 'PATTERN'; then
        cat "${file}"
    fi
done

Đối với việc học bash đó là một khởi đầu tốt. Nếu bạn chỉ cần một giải pháp nhanh chóng, hãy thử các câu trả lời sed-, awk- hoặc perl-answer. Cả hai đều tốt, nhưng chúng là ngôn ngữ riêng bạn cần (và có thể muốn) để học.

Đây là một ví dụ khá đơn giản, vì vậy nếu bạn muốn tìm hiểu thêm, bạn cũng có thể thử tương tự trong ruby, php, js (ví dụ: trong nodejs) hoặc bất kỳ ngôn ngữ nào khác cho phép truy cập tệp. Ngay cả C / C ++ hoặc Java cũng dễ quản lý với một tác vụ nhỏ.


1
Điều này về cơ bản giống như của tôi ngoại trừ việc bạn sử dụng if/elsethay vì [ ] &&.
terdon
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.