ฉันมีไฟล์ที่มีบรรทัดว่างที่ท้ายไฟล์ ฉันสามารถใช้grep
เพื่อนับจำนวนบรรทัดว่างท้ายไฟล์ด้วยชื่อไฟล์ที่ถูกส่งเป็นตัวแปรในสคริปต์ได้หรือไม่
grep
@MichaelJohn ชนะเพื่อความบริสุทธิ์ในหนังสือของฉัน
ฉันมีไฟล์ที่มีบรรทัดว่างที่ท้ายไฟล์ ฉันสามารถใช้grep
เพื่อนับจำนวนบรรทัดว่างท้ายไฟล์ด้วยชื่อไฟล์ที่ถูกส่งเป็นตัวแปรในสคริปต์ได้หรือไม่
grep
@MichaelJohn ชนะเพื่อความบริสุทธิ์ในหนังสือของฉัน
คำตอบ:
หากบรรทัดว่างอยู่ที่ท้ายเท่านั้น
grep -c '^$' myFile
หรือ:
grep -cx '' myFile
grep -cv . myFile
เป็นอีกวิธีในการเขียน (สำหรับนักกอล์ฟรหัส) แต่ฉันพบวิธีแก้ไขgrep
หากมีบรรทัดว่างที่ใดก็ได้ในไฟล์
grep -cv .
จะนับบรรทัดที่มีเฉพาะไบต์ที่ไม่ได้สร้างอักขระที่ถูกต้อง
เพียงเพื่อความสนุกสนานบางอย่างน่ากลัวsed
:
#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l
คำอธิบาย:
/./
บรรทัดที่อยู่ด้วยตัวละครใด ๆ ดังนั้น/./!
ที่อยู่บรรทัดที่ไม่ว่างเปล่า; สำหรับH
คำสั่งเหล่านั้นผนวกเข้ากับพื้นที่พัก ดังนั้นหากสำหรับแต่ละบรรทัดว่างเราได้เพิ่มหนึ่งบรรทัดในพื้นที่พักสายจะมีอีกหนึ่งบรรทัดมากกว่าจำนวนบรรทัดว่าง เราจะดูแลในภายหลัง//h
รูปแบบที่ว่างเปล่าตรงกับการแสดงออกปกติครั้งสุดท้ายซึ่งเป็นตัวละครใด ๆ ดังนั้นบรรทัดที่ไม่ว่างจะได้รับการแก้ไขและย้ายไปยังพื้นที่พักโดยh
คำสั่งเพื่อ "รีเซ็ต" บรรทัดที่รวบรวมไว้ที่ 1 เมื่อบรรทัดว่างถัดไปจะถูกต่อท้าย จะมีอีกสองครั้งตามที่คาดไว้$!d
หยุดสคริปต์โดยไม่มีเอาต์พุตสำหรับทุก ๆ ยกเว้นบรรทัดสุดท้ายดังนั้นคำสั่งเพิ่มเติมจะถูกดำเนินการหลังจากบรรทัดสุดท้ายเท่านั้น ดังนั้นเส้นว่างใด ๆ ที่เราเก็บในพื้นที่พักจะอยู่ท้ายไฟล์ ดี.//d
: d
คำสั่งจะถูกดำเนินการอีกครั้งสำหรับบรรทัดที่ไม่ว่างเปล่าเท่านั้น ดังนั้นหากบรรทัดสุดท้ายไม่ว่างเปล่าsed
จะออกโดยไม่มีเอาต์พุตใด ๆ เส้นศูนย์ ดี.x
การแลกเปลี่ยนถือพื้นที่และพื้นที่รูปแบบดังนั้นบรรทัดที่รวบรวมอยู่ในพื้นที่รูปแบบที่จะดำเนินการในขณะนี้s/\n//
แต่เราจำได้ว่ามีหนึ่งเส้นมากเกินไปดังนั้นเราจึงลดความมันโดยการลบหนึ่งขึ้นบรรทัดใหม่ด้วยwc -l
ได้GNU tac
/ tail -r
ตัวเลือกเพิ่มเติม:
tac file | awk 'NF{exit};END{print NR?NR-1:0}'
หรือ:
tac file | sed -n '/[^[:blank:]]/q;p' | wc -l
โปรดทราบว่าในผลลัพธ์ของ:
printf 'x\n '
นั่นคือที่ที่มีช่องว่างพิเศษหลังจากบรรทัดสุดท้าย (ซึ่งบางคนคิดว่าเป็นบรรทัดว่างพิเศษ แต่ตามนิยามของข้อความ POSIX ไม่ใช่ข้อความที่ถูกต้อง) พวกเขาจะให้ 0
POSIXly:
awk 'NF{n=NR};END{print NR-n}' < file
แต่นั่นหมายถึงการอ่านไฟล์เต็ม ( tail -r
/ tac
จะอ่านไฟล์ย้อนกลับจากจุดสิ้นสุดของไฟล์ที่ค้นหาได้) ที่จะช่วยให้การส่งออกของ1
printf 'x\n '
ในขณะที่คุณกำลังขอgrep
วิธีแก้ปัญหาฉันเพิ่มอันนี้อาศัยเฉพาะ GNU grep
(โอเคใช้ไวยากรณ์เชลล์และecho
... ):
#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))
ฉันกำลังทำอะไรที่นี่ $(grep -c ".*" "$1")
นับทุกบรรทัดในไฟล์จากนั้นเราจะแทนที่ไฟล์โดยไม่มีบรรทัดว่างต่อท้าย
และวิธีการรับเหล่านั้น $(grep -B42 . "$1"
จะ grep บรรทัดที่ไม่ว่างเปล่าทั้งหมดและ 42 บรรทัดก่อนหน้าดังนั้นจึงพิมพ์ทุกอย่างจนกระทั่งบรรทัดที่ไม่ว่างสุดท้ายตราบใดที่มีบรรทัดว่างที่ต่อเนื่องกันไม่เกิน 42 บรรทัดก่อนบรรทัดว่างเปล่า เพื่อหลีกเลี่ยงข้อ จำกัด นั้นฉันรับ$(grep -cv . "$1")
เป็นพารามิเตอร์สำหรับ-B
ตัวเลือกซึ่งเป็นจำนวนบรรทัดว่างทั้งหมดดังนั้นใหญ่พอเสมอ ด้วยวิธีนี้ฉันได้ตัดเส้นบรรทัดว่างเปล่าที่ต่อท้ายและสามารถใช้|grep -c ".*"
ในการนับบรรทัด
ยอดเยี่ยมใช่มั้ย (-;
tac | grep
ที่ช่องว่างแรกที่ไม่ใช่ด้วย-m -A 42
จากนั้นลบหนึ่งตัวเลือก ฉันไม่แน่ใจว่าอันไหนมีประสิทธิภาพมากกว่า แต่คุณสามารถwc -l | cut -d' ' -f1
แทนการ grepping บรรทัดว่างได้หรือไม่
tac
, wc
และcut
แต่ที่นี่ผมพยายามที่จะ จำกัด grep
ตัวเองให้ คุณสามารถเรียกมันว่าความวิปริตฉันเรียกมันว่ากีฬา (-;
อีกawk
วิธีการแก้ปัญหา ชุดรูปแบบนี้รีเซ็ตตัวนับk
ทุกครั้งที่มีบรรทัดที่ไม่ว่าง จากนั้นทุกบรรทัดจะเพิ่มตัวนับ (ดังนั้นหลังจากบรรทัดความยาวที่ไม่ว่างแรก, k==0
.) ในตอนท้ายเราจะแสดงจำนวนบรรทัดที่เรานับ
เตรียมไฟล์ข้อมูล
cat <<'X' >input.txt
aaa
bbb
ccc
X
นับบรรทัดว่างต่อท้ายในตัวอย่าง
awk 'NF {k=-1}; {k++}; END {print k+0}' input.txt
3
ในคำนิยามนี้บรรทัดว่างอาจมีช่องว่างหรืออักขระว่างอื่น ๆ มันยังว่างเปล่า ถ้าคุณอยากจะนับบรรทัดว่างมากกว่าบรรทัดว่างเปลี่ยนแปลงสำหรับNF
$0 != ""
$0 > ""
? ที่ใช้strcoll()
ซึ่งจะมีประสิทธิภาพน้อยกว่า$0 != ""
ที่ใช้memcmp()
ในการใช้งานจำนวนมาก (POSIX เคยใช้เพื่อต้องการใช้strcoll()
)
$0 > ""
อาจจะแตกต่างจาก$0 != ""
นี้ ฉันมักจะถือว่าawk
เป็นตัวดำเนินการ "ช้า" อยู่ดี (เช่นถ้าฉันรู้ว่าฉันมีชุดข้อมูลขนาดใหญ่เป็นอินพุตและการประมวลผลเป็นเวลาที่สำคัญฉันจะเห็นสิ่งที่ฉันสามารถทำได้เพื่อลดจำนวนที่awk
ต้องดำเนินการ - ฉัน ได้ใช้grep | awk
โครงสร้างในสถานการณ์ดังกล่าว) แต่ต้องมีลักษณะอย่างรวดเร็วในสิ่งที่ผมถือว่าเป็นความหมาย POSIXฉันไม่สามารถเห็นการอ้างอิงถึงอย่างใดอย่างหนึ่งหรือstrcoll()
memcmp()
ฉันกำลังคิดถึงอะไร
strcoll()
== สตริงจะนำมาเปรียบเทียบโดยใช้ลำดับเรียงสถานที่เฉพาะเจาะจง เปรียบเทียบกับรุ่นก่อนหน้า ฉันเป็นคนหนึ่งที่นำมันขึ้นมา ดูเพิ่มเติมaustingroupbugs.net/view.php?id=963
a <= b && a >= b
a == b
อุ๊ย!
awk
หรือbash
(สำหรับ[[ a < b ]]
ผู้ประกอบการ) ใน en_US.UTF-8 สถานที่ในระบบ GNU เช่นสำหรับ①
VS ②
เช่น (สำหรับbash
ไม่มี<
, >
, =
กลับจริงสำหรับผู้ที่) อาจเป็นข้อผิดพลาดในคำจำกัดความของสถานที่เหล่านั้นมากกว่าใน bash / awk
เพื่อนับจำนวนบรรทัดว่างต่อเนื่องที่ส่วนท้ายของไฟล์
โซลูชั่นSolid awk
+ tac
:
ตัวอย่างinput.txt
:
$ cat input.txt
aaa
bbb
ccc
$ # command line
การกระทำ:
awk '!NF{ if (NR==++c) { cnt++ } else exit }END{ print int(cnt) }' <(tac input.txt)
!NF
- ตรวจสอบให้แน่ใจว่าบรรทัดปัจจุบันว่างเปล่า (ไม่มีฟิลด์)NR==++c
- สร้างความมั่นใจในลำดับบรรทัดว่างที่ต่อเนื่องกัน ( NR
- จำนวนบันทึก++c
- เคาน์เตอร์เสริมที่เพิ่มขึ้นอย่างเท่าเทียมกัน)cnt++
- ตัวนับของบรรทัดว่างผลลัพธ์:
3
IIUC สคริปต์ต่อไปนี้ที่เรียกว่าcount-blank-at-the-end.sh
จะทำงาน:
#!/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"
ตัวอย่างการใช้งาน:
$ ./count-blank-at-the-end.sh FILE
4
ผมทดสอบในGNU bash
, และในAndroid mksh
ksh
ทางเลือกอื่น ๆPython
:
ตัวอย่างอินพุต. txt:
$ cat input.txt
aaa
bbb
ccc
$ # command line
การกระทำ:
python -c 'import sys, itertools; f=open(sys.argv[1]);
lines=list(itertools.takewhile(str.isspace, f.readlines()[::-1]));
print(len(lines)); f.close()' input.txt
ผลลัพธ์:
3
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.takewhile