ค้นหาบรรทัดใด ๆ ที่เกินความยาวที่กำหนด


52

เป็นไปได้หรือไม่ที่จะหาบรรทัดในไฟล์ที่มีความยาวเกิน 79 ตัวอักษร?

คำตอบ:


89

เพื่อลดความเร็ว (ในระบบ GNU ในภาษา UTF-8 และ ASCII input) ตามการทดสอบของฉัน:

grep '.\{80\}' file

perl -nle 'print if length$_>79' file

awk 'length>79' file

sed -n '/.\{80\}/p' file

ยกเว้นperl¹หนึ่ง (หรือสำหรับawk/ grep/ sedการใช้งาน (ชอบmawkหรือ busybox) ที่ไม่สนับสนุนอักขระหลายไบต์) ที่นับยาวในแง่ของจำนวนตัวอักษร (ตามLC_CTYPEการตั้งค่าของสถานที่เกิดเหตุ) แทนไบต์

หากมีไบต์ในอินพุตที่ไม่ได้เป็นส่วนหนึ่งของอักขระที่ถูกต้อง (ซึ่งบางครั้งเกิดขึ้นเมื่อชุดอักขระของโลแคลคือ UTF-8 และอินพุตอยู่ในการเข้ารหัสที่แตกต่างกัน) จากนั้นขึ้นอยู่กับการใช้งานโซลูชันและเครื่องมือ อย่างใดอย่างหนึ่งจะนับเป็น 1 ตัวอักษรหรือ 0 .หรือไม่ตรง

ตัวอย่างเช่นบรรทัดที่ประกอบด้วย 30 asa 0x80 byte, 30 bs, 0x81 byte และ 30 UTF-8 és (เข้ารหัสเป็น 0xc3 0xa9) ในโลแคล UTF-8 จะไม่ตรง.\{80\}กับ GNU grep/ sed(ในรูปแบบ standalone 0x80 byte ไม่ตรง.) จะมีความยาว 1 + 30 + 30 + 1 + 2 * 30 = 122 ด้วยperlหรือmawk3 * 30 = gawk90

หากคุณต้องการที่จะนับในแง่ของไบต์แก้ไขสถานที่จะมีCLC_ALL=C grep/awk/sed...

นั่นจะมีวิธีแก้ปัญหาทั้งหมด 4 ข้อพิจารณาว่าบรรทัดด้านบนมี 122 ตัวอักษร ยกเว้นในperlและเครื่องมือ GNU คุณยังคงมีปัญหาที่อาจเกิดขึ้นกับบรรทัดที่มีอักขระ NUL (0x0 ไบต์)


¹ perlพฤติกรรมได้รับผลกระทบโดยPERL_UNICODEตัวแปรสภาพแวดล้อมแม้ว่า


"ประสิทธิภาพ" หมายถึงอะไร?
rowantran

ฉันคิดว่าการทำธุรกิจหมายถึงการพิมพ์ที่มีประสิทธิภาพ awkสามารถเข้ามาใกล้มากขึ้นถ้าคุณดรอป($0)ซึ่งโดยปริยายอยู่แล้ว;)
Thor

9
BTW ถ้าคุณยึด regexp เพื่อเริ่มต้นของบรรทัดกับมันได้เร็วขึ้นเล็กน้อยเช่น^ grep '^.\{80\}' file
CAS

4
วิธีการแก้ปัญหา perl ไม่บัญชีสำหรับการเข้ารหัสขนาดตัวแปรเช่น UTF-8 ซึ่งแตกต่างจากโซลูชั่นอื่น ๆ ทั้งหมด
BatchyX

6
ค่า N ที่มีขนาดใหญ่เพียงพอล้มเหลวด้วย grep แต่สำเร็จด้วย awk (เช่นgrep '^.\{1000\}' fileส่งคืนgrep: invalid repetition count(s)ขณะที่ทำawk 'length>1000' fileสำเร็จ)
mdahlman

1

วิธีเชลล์:

while IFS= read -r line || [ -n "$line" ];
do 
    [ "${#line}" -gt 79 ] && printf "%s\n" "$line"
done < input.txt

วิธีการหลาม:

python -c 'import sys;f=open(sys.argv[1]);print "\n".join([ l.strip() for l in f if len(l) >79 ]);f.close()' input.txt

หรือเป็นสคริปต์สั้น ๆ เพื่อให้อ่านง่าย:

#!/usr/bin/env python
import sys

with open(sys.argv[1]) as f:
    for line in f:
        if len(line) > 79:
            print line.strip()

หากเราต้องการยกเว้นอักขระขึ้นบรรทัดใหม่\nจากการคำนวณเราสามารถif len(line) > 79ทำได้if len(line.strip()) > 79

หมายเหตุด้านข้าง: นี่คือไวยากรณ์ Python 2.7 ใช้print()สำหรับ Python 3

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.