`wc -l` ทำงานอย่างไร


11

ฉันต้องอ่านไฟล์ขนาดใหญ่และก่อนที่จะเริ่มอ่านฉันต้องรู้จำนวนบรรทัดทั้งหมดในไฟล์ (ซึ่งมีหน่วยเป็นล้าน)

ฉันใช้งานโซลูชั่นจำนวนมากและพบวิธีแก้ปัญหาแล้ว แต่ในระหว่างการค้นหาของฉันฉันคิดว่าจะดูว่าwc -lทำงานอย่างไร ฉันไม่พบสิ่งใดใน Google

แม้ว่าฉันจะได้พบวิธีแก้ปัญหาของฉันแล้วฉันก็ยังอยากรู้ว่าwc -lมันทำงานอย่างไรเพราะมันสามารถคำนวณจำนวนบรรทัดของไฟล์ที่มี 92 ล้านบรรทัดในไม่กี่วินาที!

อย่างไร?


คำตอบ:


20

มันอ่านไฟล์ทั้งหมดและนับจำนวนของการสิ้นสุดบรรทัด การนับตอนจบบรรทัดนั้นถูกจริงๆ เวลาส่วนใหญ่ที่ใช้ในการอ่านไฟล์ หากไฟล์เกิดขึ้น (ส่วนใหญ่) ในแคชบัฟเฟอร์นั่นจะถูกเช่นกัน มิฉะนั้นจะขึ้นอยู่กับความเร็วของการจัดเก็บไฟล์ของคุณ

กล่าวอีกนัยหนึ่งไม่มีเวทมนตร์


มันอ่านไฟล์ทั้งหมดและนับจำนวนของการสิ้นสุดบรรทัดหรือไม่ เมื่อต้องการไปยังจุดสิ้นสุดของบรรทัดมันไม่ได้อ่านทั้งบรรทัดจนกว่าจะถึงจุดสิ้นสุดหรือไม่ และนั่นหมายความว่ามันอ่านไฟล์ทั้งหมดใช่มั้ย
detraveller

@detraveller: ใช่มันอ่านไฟล์ทั้งหมดเหมือนที่ฉันพูด มันไม่ได้อ่านทีละบรรทัดหรือทั้งหมดในคราวเดียว แต่มันจะอ่านตัวละครทุกตัวและนับว่าตัวละครเหล่านั้นเป็นตัวละครที่มีจำนวนมากแค่ไหน
rici

7

WC เพียงแค่อ่านไฟล์ในบล็อกของไบต์ดิบ (ดีกว่าในทวีคูณของขนาดบล็อกธรรมชาติของระบบไฟล์พื้นฐานที่ไฟล์ตั้งอยู่)
จากนั้นจะทำการสแกนผ่านบัฟเฟอร์เพื่อนับจำนวนอักขระที่อยู่ท้ายบรรทัด (นอกจากนี้ยังนับช่องว่างแท็บฟอร์มฟีดและอักขระพิเศษอื่น ๆ ในกรณีที่คุณต้องการข้อมูลอื่นนอกเหนือจากเอาต์พุต -l)

การอ่านจากดิสก์เป็นส่วนที่มีราคาแพงในแง่ของความเร็ว การสแกนของบัฟเฟอร์นั้นใช้เวลานานพอสมควร

สมมติว่าคุณมี 90 ล้านบรรทัดโดยเฉลี่ย 100 ตัวอักษรต่อบรรทัด
นั่นคือประมาณ 9.000.000.000 ตัวอักษรหรือประมาณ 860 MB
พีซีที่เหมาะสมกับไดรฟ์ SATA-3Gb / s จะทำเช่นนั้นภายใน 10 วินาที แม้ในระบบไฟล์ที่ค่อนข้างช้าโดยมีกิจกรรมอื่น ๆ เกิดขึ้นในเวลาเดียวกัน
เครื่องจักรที่รวดเร็วพร้อมการปรับแต่งประสิทธิภาพและระบบไฟล์ที่ปรับให้เหมาะสมสามารถทำได้ภายใน 5 วินาทีแม้จะไม่ต้องหันไปใช้ SATA-6G และไดรฟ์ SSD ก็ตาม


มันแค่สแกนผ่านบัฟเฟอร์เพื่อนับจำนวน\nอักขระสุดท้ายของบรรทัด ( ) - "-l, - บรรทัดพิมพ์จำนวนบรรทัดใหม่ \ n \" - แยกออกมาจากwc.c
Rahul Patil

@RahulPatil การใช้งานส่วนใหญ่ทำมากกว่าแค่การนับบรรทัดใหม่ ดูตัวอย่างที่กล่าวถึงในความคิดเห็นด้านบน นั่นคือที่มาของ wc ตามที่ใช้ในอรรถประโยชน์หลักของ Linux
Tonny

ใช่ .. ฉันได้เห็นแล้ว .. ฉันเพิ่งพูดถึงเพราะคำถามเกี่ยวกับwc -l.. ขอโทษ ...
Rahul Patil

3

ยินดีต้อนรับสู่โลกของซอฟต์แวร์ฟรี คุณสามารถดูซอร์สโค้ดได้ตลอดเวลา

ถึงแม้ว่าผมจะต้องยอมรับว่าฉันไม่ได้เป็นโปรแกรมเมอร์ C ดังนั้นฉันไม่ได้เป็นคนที่จริงๆสามารถอธิบายรหัสสำหรับคุณ (และฉันจะได้รับการ insterested ตัวเอง)

สิ่งที่ฉันรู้คือเนื่องจาก wc ไม่ได้เปิดไฟล์เอง แต่ขอให้ระบบปฏิบัติการทำสิ่งนี้ส่วนใหญ่ขึ้นอยู่กับระบบปฏิบัติการและแน่นอนวิธีการจัดเก็บไฟล์ นอกเหนือจากนั้นฉันคาดหวังว่าการเขียนโปรแกรมที่ถูกต้องจะต้องอยู่ในสถานที่เช่นไม่พยายามอ่านไฟล์ทั้งหมดในคราวเดียวเป็นต้น


คุณหมายถึงอะไรโดยการพูดว่า 'ไม่พยายามอ่านไฟล์ทั้งหมดพร้อมกัน'
detraveller

ฉันหมายถึงการโหลดไฟล์ไปยังหน่วยความจำพูดถึงสตริง / อาร์เรย์เดียว ในชุมชน Perl สิ่งนี้เรียกว่า slurping และมันเป็นวิธีแก้ปัญหาที่รวดเร็วและสกปรกซึ่งก็โอเคเมื่อคุณรู้ว่าคุณกำลังอ่านสองสามบรรทัด แต่การป้อนไฟล์ขนาดใหญ่ลงในหน่วยความจำในเวลาเดียวกันเป็นความคิดที่ดี
Alois Mahdal

1
ในอีกทางหนึ่งคุณสามารถอ่านพูด 64 กิโลไบต์นับจำนวนบรรทัดใหม่และโยนมันออกไปทำซ้ำ ... ด้วยวิธีนี้คุณจะกินอะไรมากไปกว่า 64 KiB ไม่ว่าไฟล์จะใหญ่แค่ไหนก็ตาม (มันง่ายกว่าเมื่อคุณรู้ว่าบรรทัดใหม่สามารถมี 2 ไบต์และแยกจากกันระหว่าง 2 ชิ้นตอนนี้เป็นที่ที่ความสนุกเริ่ม)
Alois Mahdal

ไม่สำคัญเกินไป แต่: "เนื่องจาก wc ไม่ได้เปิดไฟล์เอง แต่ขอให้ระบบปฏิบัติการทำ" - ไม่แน่ใจว่าคุณหมายถึงอะไร แต่ฉันสงสัยว่านี่ถูกต้อง แน่นอนว่ามันอ่านตัวละครทั้งหมดด้วยตัวเอง
Arjan

2
@Arjan แม้ว่าจะถูกต้องจริง ๆ : ยกเว้นระบบฝังตัว แต่โปรแกรมแทบจะไม่อ่านตัวเองจุดรวมทั้งหมดของเคอร์เนลและระบบปฏิบัติการคือการทำงานให้กับพวกเขา อันที่จริง open (), close (), read () (ไม่ว่าจะเป็น Linux, Windows, ซ็อกเก็ตหรือไฟล์) เป็นระบบที่เรียกว่าโปรแกรมจริงไม่มีความคิดในการทำงานภายใน
Alois Mahdal
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.