วิธีการแสดงบางบรรทัดจากไฟล์ข้อความใน Linux?


85

ฉันเดาว่าทุกคนรู้ว่าอรรถประโยชน์บรรทัด Linux cmd headและtailประโยชน์ headอนุญาตให้คุณพิมพ์บรรทัด X แรกของไฟล์tailทำเช่นเดียวกัน แต่พิมพ์จุดสิ้นสุดของไฟล์ คำสั่งที่ดีในการพิมพ์ที่ตรงกลางของไฟล์คืออะไร? บางอย่างเช่นmiddle --start 10000000 --count 20(พิมพ์ 10'000'000th จนถึง th 10'000'010 บรรทัด)

ฉันกำลังมองหาบางอย่างที่จะจัดการกับไฟล์ขนาดใหญ่ได้อย่างมีประสิทธิภาพ ฉันพยายามtail -n 10000000 | head 10แล้วมันก็ช้ามาก


5
อาจเป็นไปได้ซ้ำกับserverfault.com/questions/101900/…
Kyle Brandt

คำตอบ:


111
sed -n '10000000,10000020p' filename

คุณอาจสามารถเร่งความเร็วได้เช่นนี้:

sed -n '10000000,10000020p; 10000021q' filename

ในคำสั่งเหล่านั้นตัวเลือก-nทำให้sed"ระงับการพิมพ์พื้นที่รูปแบบอัตโนมัติ" pคำสั่ง "พิมพ์ [s] พื้นที่รูปแบบปัจจุบัน" และq"คำสั่งทันทีเลิก [s] สคริปต์ sed โดยไม่ต้องประมวลผลการป้อนข้อมูลใด ๆ เพิ่มเติม ..." คำพูดมาจากหน้าsed man

โดยวิธีการที่คำสั่งของคุณ

tail -n 10000000 filename | head 10

เริ่มต้นที่บรรทัดที่สิบล้านจากจุดสิ้นสุดของไฟล์ในขณะที่คำสั่ง "กลาง" ของคุณดูเหมือนจะเริ่มต้นที่สิบล้านจากจุดเริ่มต้นซึ่งจะเทียบเท่ากับ:

head -n 10000010 filename | tail 10

ปัญหาคือไฟล์ที่ไม่ได้เรียงลำดับที่มีบรรทัดความยาวผันแปรได้กระบวนการใดก็ตามที่จะต้องผ่านการนับบรรทัดใหม่ ทางลัดสำหรับวิธีนี้ไม่มีทาง

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

* ฉันตั้งใจจะโพสต์และอัปเดตสคริปต์อื่นอีกครั้ง บางทีฉันอาจจะได้รอบหนึ่งวันนี้


นี่คือsedรุ่นของชาร์ลส์ฟังก์ชั่น:middle middle() { local s=$1 c=$2; shift 2; sed -n "$s,$(($s + $c -1))p; $(($s + $c))q" "$@"; }มันจะจัดการกับอาร์กิวเมนต์ไฟล์หลายไฟล์ชื่อไฟล์ที่มีช่องว่าง ฯลฯ หลายไฟล์จะถูกประมวลผลร่วมกันราวกับว่าพวกเขาได้รับ catted ในลักษณะเดียวกันกับที่ทำsedตามปกติ (ดังนั้น 1,000 1,000 กลาง file1 file1 file2 จะขยายทั่วทั้งไฟล์แรกจนถึงจุดเริ่มต้น ของอันที่สองหากอันแรกมีน้อยกว่า 1100 บรรทัด)
Dennis Williamson

ฟังก์ชั่นในความคิดเห็นก่อนหน้าของฉันสามารถเรียกด้วยพารามิเตอร์ชื่อไฟล์: middle startline count filenameหรือหลายชื่อไฟล์: middle startline count file1 file2 file3หรือด้วยการเปลี่ยนเส้นทาง: middle startline count < filenameหรือในท่อ: some_command | เริ่มต้นกลางนับ 'หรือcat file* | middle startline count
เดนนิสวิลเลียมสัน

ไม่ควร `ในคำสั่ง sed ของคุณเป็น '? ฉันไม่สามารถทำงานกับ backtick ได้ แต่ใช้งานได้ดีกับข้อความอ้างอิงเดี่ยว
Ian Hunter

@beanland: ใช่มันเป็นคำผิด ฉันแก้ไขมันแล้ว ขอบคุณ
Dennis Williamson

1
@kev: ฉันได้เพิ่มคำอธิบายลงในคำตอบของฉัน
Dennis Williamson

28

ฉันพบการใช้งานต่อไปนี้ของ sed

sed -n '10000000,+20p'  filename

หวังว่ามันจะเป็นประโยชน์กับใครบางคน!


เป็นการดีที่จะรู้ว่ามีทางเลือกอื่นสำหรับอาร์กิวเมนต์บรรทัดสุดท้ายที่เสนอโดย Dennis: การนับบรรทัดเป็นsed -nอาร์กิวเมนต์ที่สองซึ่งทำให้อ่านได้ง่าย
user3123159

ตัวอย่างการใช้งาน: extract_lines(){sed -n "$1,+$2p" <file>}ซึ่งเขียนไปยัง stdout
user3123159

4

นี่เป็นครั้งแรกที่ฉันโพสต์ที่นี่! อย่างไรก็ตามอันนี้ง่าย สมมติว่าคุณต้องการดึงบรรทัด 8872 จากไฟล์ของคุณชื่อ file.txt นี่คือวิธีที่คุณทำ:

cat -n file.txt | grep '^ * 8872'

ตอนนี้คำถามคือหา 20 บรรทัดหลังจากนี้ เพื่อให้บรรลุสิ่งนี้คุณต้องทำ

cat -n file.txt | grep -A 20 '^ * 8872'

สำหรับบรรทัดรอบ ๆ หรือก่อนเห็นแฟล็ก -B และ -C ในคู่มือ grep


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

หลายบรรทัด: cat -n file.txt | grep "^ \ s \ + (10 \ | 20 \ | 30) \ s \ +"
เจฟฟรีย์อัศวิน

cat -n file.txt | grep '^ *1'ให้ผลลัพธ์ทุกเส้นที่มี 1 ทางด้านขวา วิธีการส่งออกบรรทัดที่ 1 ด้วยเทคนิคนี้? ฉันรู้ว่าฉันสามารถหัว -n 1 .... แต่วิธีการใช้ grep?
Sean87

1

คำตอบที่ไม่ดีของเดนนิสเป็นหนทางไป แต่ใช้เพียงหัวและหางภายใต้ทุบตี:

middle () {head -n $ [$ 1 + $ 2] | หาง -n $ 2; }

การสแกน $ 1 + $ 2 บรรทัดแรกสองครั้งจึงแย่กว่าคำตอบของเดนนิส แต่คุณไม่จำเป็นต้องจำจดหมายที่น่าเบื่อเหล่านี้ทั้งหมดเพื่อใช้ ....


การใช้$[...]จะเลิกอย่างน้อยในทุบตี นอกจากนี้คุณยังขาดพารามิเตอร์ไฟล์
Dennis Williamson

@Dennis: ไม่มีพารามิเตอร์ขาดหายไป: คุณกำลังหมายถึงการใช้วิธีนี้ใน stdin middle 10 10 < /var/log/auth.logเป็นต่อ
Charles Stewart

1

ใช้คำสั่งต่อไปนี้เพื่อรับช่วงของบรรทัดเฉพาะ

awk 'NR < 1220974{next}1;NR==1513793{exit}' debug.log | tee -a test.log

ที่นี่ debug.log เป็นไฟล์ของฉันซึ่งประกอบด้วยเส้นขาดและฉันใช้ในการพิมพ์บรรทัดจาก 1220974 หมายเลขบรรทัดเพื่อ 1513793 ไปยังไฟล์ test.log หวังว่ามันจะมีประโยชน์สำหรับการจับช่วงของเส้น


คำตอบเดียวกับserverfault.com/a/641252/140016 downvoted
Deer Hunter

มันไม่ได้เป็นคำตอบเดียวกัน สิ่งนี้ควรจะเร็วกว่าสำหรับไฟล์ขนาดใหญ่เนื่องจากมันยกเลิกจริงหลังจากพิมพ์บรรทัดสุดท้ายแทนที่จะสแกนไฟล์ต่อไป
phobic

0

รุ่น ruby ​​oneliner

ruby -pe 'next unless $. > 10000000 && $. < 10000020' < filename.txt

มันจะมีประโยชน์กับใครบางคน การแก้ปัญหาด้วย 'sed' ที่ Dennis และ Dox จัดทำนั้นดีมากถึงแม้จะดูเหมือนเร็วกว่าก็ตาม




0

หากคุณรู้จัก line numebrs ให้บอกว่าคุณต้องการรับบรรทัด 1, 3 และ 5 จากไฟล์ให้พูด / etc / passwd:

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd

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