Đếm số lượng dòng trống ở cuối tập tin


11

Tôi có một tập tin với các dòng trống ở cuối tập tin. Tôi có thể sử dụng grepđể đếm số dòng trống ở cuối tệp với tên tệp được truyền dưới dạng biến trong tập lệnh không?


để đếm số dòng trống liên tiếp ?
RomanPerekhrest

2
@RomanPerekhrest Tôi sẽ nói như vậy, nếu không họ sẽ không "ở cuối tập tin"?
Sparhawk

'grep -cv -P' \ S 'tên tệp' sẽ đếm tổng số dòng trống trong tệp. Con số cuối cùng chỉ đánh thuế não của tôi!
MichaelJohn

OP đã yêu cầu grep@MichaelJohn giành chiến thắng vì sự thuần khiết trong cuốn sách của tôi.
bu5hman

2
@ bu5hman Nhưng (như anh thừa nhận) không trả lời câu hỏi. Cũng không phải của bạn, thực sự.
Sparhawk

Câu trả lời:


11

Nếu các dòng trống chỉ ở cuối

grep  -c '^$' myFile

hoặc là:

grep -cx '' myFile

Bị đánh bại để chỉnh sửa trong vài giây, chết tiệt
bu5hman

grep -cv . myFilelà một cách khác để viết nó (đối với người chơi golf mã). Nhưng tôi đã tìm thấy một giải pháp grepnếu có các dòng trống ở bất cứ đâu trong tệp.
Philippos

2
@Philippos, grep -cv .cũng sẽ đếm các dòng chỉ chứa các byte không tạo thành các ký tự hợp lệ.
Stéphane Chazelas

11

Chỉ để cho vui, một số ma quái sed:

#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l

Giải trình:

  • /./địa chỉ các dòng với bất kỳ ký tự, vì vậy /./!địa chỉ các dòng không trống; đối với những người đó, Hlệnh nối chúng vào không gian giữ. Do đó, nếu với mỗi dòng trống, chúng ta đã thêm một dòng vào không gian giữ, luôn có một dòng nhiều hơn số dòng trống. Chúng tôi sẽ chăm sóc cho điều đó sau.
  • //hmẫu trống khớp với biểu thức chính quy cuối cùng, là bất kỳ ký tự nào, do đó, bất kỳ dòng không trống nào được xử lý và di chuyển đến không gian giữ bằng hlệnh để "đặt lại" các dòng đã thu thập thành 1. Khi dòng trống tiếp theo sẽ được nối thêm, Sẽ có hai lần nữa, như mong đợi.
  • $!ddừng tập lệnh mà không có đầu ra cho mỗi nhưng dòng cuối cùng, vì vậy các lệnh tiếp theo chỉ được thực hiện sau dòng cuối cùng. Vì vậy, bất cứ dòng trống nào chúng tôi thu thập trong không gian giữ đều ở cuối tệp. Tốt
  • //d: dLệnh được thực hiện lại chỉ cho các dòng không trống. Vì vậy, nếu dòng cuối cùng không trống, sedsẽ thoát mà không có đầu ra. Không dòng. Tốt
  • x trao đổi giữ không gian và không gian mẫu, vì vậy các dòng thu thập được trong không gian mẫu bây giờ sẽ được xử lý.
  • Nhưng chúng tôi nhớ rằng có một dòng quá nhiều, vì vậy chúng tôi giảm nó bằng cách xóa một dòng mới s/\n//.
  • Võngà! Số dòng phù hợp với số dòng trống ở cuối (lưu ý rằng dòng đầu tiên sẽ không trống, nhưng ai quan tâm), vì vậy chúng tôi có thể đếm chúng wc -l.

8

Một số GNU tac/ tail -rtùy chọn khác:

tac file | awk 'NF{exit};END{print NR?NR-1:0}'

Hoặc là:

tac file | sed -n '/[^[:blank:]]/q;p' | wc -l

Lưu ý rằng trên đầu ra của:

printf 'x\n '

Đó là, nơi có thêm một khoảng trắng sau dòng đầy đủ cuối cùng (mà một số người có thể coi là một dòng trống thêm, nhưng theo định nghĩa POSIX của văn bản, không phải là văn bản hợp lệ), những cái đó sẽ cho 0.

POSIXly:

awk 'NF{n=NR};END{print NR-n}' < file

nhưng điều đó có nghĩa là đọc tệp đầy đủ ( tail -r/ tacsẽ đọc tệp ngược từ cuối trên các tệp có thể tìm kiếm). Điều đó mang lại cho 1đầu ra của printf 'x\n '.


6

Vì bạn thực sự đang yêu cầu một grepgiải pháp, tôi chỉ thêm giải pháp này dựa trên GNU grep(được, cũng sử dụng cú pháp shell và echo...):

#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))

Tôi đang làm gì ở đây? $(grep -c ".*" "$1")đếm tất cả các dòng trong tệp, sau đó chúng tôi trừ tệp mà không có các dòng trống.

Và làm thế nào để có được những? $(grep -B42 . "$1"sẽ grep tất cả các dòng không trống và 42 dòng trước chúng, vì vậy nó sẽ in mọi thứ cho đến dòng không trống cuối cùng, miễn là không có hơn 42 dòng trống liên tiếp trước một dòng không trống. Để tránh giới hạn đó, tôi lấy $(grep -cv . "$1")làm tham số cho -Btùy chọn, đó là tổng số dòng trống, vì vậy luôn đủ lớn. Bằng cách này, tôi đã loại bỏ các dòng trống ở cuối và có thể sử dụng |grep -c ".*"để đếm các dòng.

Rực rỡ phải không? (-;


+1 vì mặc dù đó là mã khủng khiếp, nhưng về mặt kỹ thuật, nó trả lời câu hỏi khi được hỏi và tôi không thể đánh dấu bạn xuống ;-)
roaima

Grepmeister. Chúng tôi không xứng đáng.
bu5hman

+1 cho sự ngoan cố. Một tùy chọn khác (có thể nhanh hơn?) Sẽ là tac | grepkhông trống đầu tiên -m -A 42, sau đó trừ đi. Tôi không chắc cái nào hiệu quả hơn, nhưng bạn cũng có thể wc -l | cut -d' ' -f1thay vì gồng những dòng trống?
Sparhawk

Vâng, chắc chắn, bạn có thể làm rất nhiều thứ với tac, wccut, nhưng ở đây tôi đã cố gắng hạn chế bản thân mình grep. Bạn có thể gọi nó là sự ngoan cố, tôi gọi nó là thể thao. (-;
Philippos

5

Một awkgiải pháp khác . Biến thể này đặt lại bộ đếm kmỗi lần có một dòng không trống. Sau đó, mỗi dòng tăng bộ đếm. (Vì vậy, sau dòng có độ dài không trống đầu tiên , k==0.) Cuối cùng, chúng tôi xuất số lượng dòng chúng tôi đã đếm.

Chuẩn bị tệp dữ liệu

cat <<'X' >input.txt
aaa

bbb
ccc



X

Đếm các dòng trống trong mẫu

awk 'NF {k=-1}; {k++}; END {print k+0}' input.txt
3

Trong định nghĩa này, một dòng trống có thể chứa khoảng trắng hoặc các ký tự trống khác; Nó vẫn trống. Nếu bạn thực sự muốn đếm dòng trống chứ không phải là dòng trống, thay đổi NFcho $0 != "".


Tại sao $0 > ""? Điều đó sử dụng strcoll()sẽ kém hiệu quả hơn so với $0 != ""sử dụng memcmp()trong nhiều triển khai (POSIX được sử dụng để yêu cầu sử dụng strcoll()mặc dù).
Stéphane Chazelas

@ StéphaneChazelas Tôi chưa nghĩ $0 > ""có thể khác $0 != "". Tôi có xu hướng điều trị awknhư một nhà điều hành "chậm" anyway (ví dụ rằng nếu tôi biết tôi đã có một bộ dữ liệu lớn như đầu vào và xử lý là thời điểm quan trọng, tôi sẽ thấy những gì tôi có thể làm để giảm bớt số tiền awkphải xử lý - Tôi đã sử dụng các grep | awkcấu trúc trong các tình huống như vậy). Tuy nhiên, sau khi đã có một cái nhìn nhanh chóng vào những gì tôi giả sử là nét POSIX Tôi không thể nhìn thấy bất kỳ tài liệu tham khảo cho một trong hai strcoll()hoặc memcmp(). Tôi đang thiếu gì?
roaima

strcoll()== các chuỗi sẽ được so sánh bằng cách sử dụng trình tự đối chiếu cụ thể của miền địa phương . So sánh với phiên bản trước . Tôi là người đưa nó lên. Xem thêm austingroupbugs.net/view.php?id=963
Stéphane Chazelas

@ StéphaneChazelas một cách thực hiện a <= b && a >= bkhông nhất thiết phải giống như a == b. Ôi!
roaima

Đó là trường hợp của GNU awkhoặc bash(cho nó [[ a < b ]]khai thác) trong en_US.UTF-8 miền địa phương trên các hệ thống GNU ví dụ cho vs ví dụ (cho bash, không ai trong số <, >, =trở thành sự thật cho những người). Có thể cho rằng đó là một lỗi trong định nghĩa của những địa phương đó nhiều hơn trong bash / awk
Stéphane Chazelas

2

để đếm số dòng trống liên tiếp ở cuối tập tin

Dung dịch rắn awk+tac

Mẫu input.txt:

$ cat input.txt
aaa

bbb
ccc



$  # command line 

Hành động:

awk '!NF{ if (NR==++c) { cnt++ } else exit }END{ print int(cnt) }' <(tac input.txt)
  • !NF- đảm bảo dòng hiện tại trống (không có trường)
  • NR==++c- đảm bảo thứ tự liên tiếp của các dòng trống. ( NR- số bản ghi, ++c- bộ đếm phụ tăng dần)
  • cnt++- bộ đếm dòng trống

Đầu ra:

3

1

IIUC, đoạn script sau được gọi count-blank-at-the-end.shsẽ thực hiện công việc:

#!/usr/bin/env sh

count=$(tail -n +"$(grep . "$1" -n | tail -n 1 | cut -d: -f1)" "$1" | wc -l)
num_of_blank_lines=$((count - 1))

printf "%s\n" "$num_of_blank_lines"

Ví dụ sử dụng:

$ ./count-blank-at-the-end.sh FILE
4

Tôi đã thử nó trong GNU bash, Android mkshvà trong ksh.


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.