ตรงข้ามของหาง: ทุกบรรทัดยกเว้นเส้นสุดท้าย n


36

ฉันจะยกเลิกบรรทัดสุดท้ายของไฟล์ด้วยตัวกรองบรรทัดคำสั่ง unix ได้อย่างไร

นั่นจะเป็นสิ่งที่ตรงกันข้ามtail: tailทิ้งเส้น n แรก แต่ท่อส่วนที่เหลือผ่าน แต่ฉันต้องการคำสั่งที่จะท่อทุกอย่างผ่านยกเว้นเส้นสุดท้าย n

น่าเสียดายที่ฉันไม่ได้พบอะไรแบบนั้น - ก็headไม่ช่วยเช่นกัน แก้ไข : อย่างน้อยใน Solaris มันไม่ได้มีข้อโต้แย้งเชิงลบ

อัปเดต: ฉันส่วนใหญ่สนใจวิธีการแก้ปัญหาที่ใช้งานได้กับไฟล์ขนาดใหญ่เช่นล็อกไฟล์ซึ่งคุณอาจต้องการตรวจสอบสิ่งที่เกิดขึ้นในนาทีสุดท้าย


FYI เมื่อใช้ส่วนหัว: การวาง '-' ไว้ข้างหน้าหมายเลขด้วยตัวเลือก -n จะพิมพ์บรรทัดทั้งหมดของแต่ละไฟล์ แต่ไม่ใช่บรรทัดสุดท้ายที่แสดงด้านล่าง
G Koe

คำตอบ:


38

หากคุณมี GNU headคุณสามารถใช้

head -n -5 file.txt

การพิมพ์ทั้งหมด แต่ช่วง 5 file.txtบรรทัด

หากhead -nไม่มีข้อโต้แย้งเชิงลบลอง

head -n $(( $(wc -l file.txt | awk '{print $1}') - 5 )) file.txt

11
(และสวดภาวนาที่file.txtมีความยาวอย่างน้อยหกบรรทัด ... )
CVn

1
น่าเสียดายที่เวอร์ชันที่ไม่ใช่ GNU นี้ไม่สามารถทำงานร่วมกับสตรีมได้เช่นกัน
Armand

1
@ MichaelKjörlingอย่างน้อยใน Ubuntu ที่ไม่ใช่ปัญหา หากไฟล์มีบรรทัดน้อยกว่าที่ระบุในheadเอาต์พุตว่างจะถูกส่งคืนโดยไม่มีข้อผิดพลาด
Alphaaa

ถ้าฉันไม่ผิดหัว -n 5 จะพิมพ์ 5 บรรทัดแรกไม่ใช่ทั้งหมด แต่ 5 ครั้งสุดท้าย ...
pypmannetjies

8
head file.txt               # first 10 lines
tail file.txt               # last 10 lines
head -n 20 file.txt         # first 20 lines
tail -n 20 file.txt         # last 20 lines
head -20 file.txt           # first 20 lines
tail -20 file.txt           # last 20 lines
head -n -5 file.txt         # all lines except the 5 last
tail -n +5 file.txt         # all lines except the 4 first, starts at line 5

1
ส่วนเสริมนี้ที่ไม่ได้รับคำตอบในคำตอบที่ยอมรับคืออะไร นอกจากนี้เช่นเดียวกับคำตอบอื่น ๆ คำอธิบายสองสามบรรทัดของคำตอบของคุณจะช่วยปรับปรุง
music2myear

1
สรุปที่ดีมาก
ruanhao

5

นี่เป็นวิธีง่ายๆในการลบบรรทัดสุดท้ายซึ่งใช้งานได้กับ BSD เป็นต้น

sed '$d' input.txt

นิพจน์อ่าน "ในบรรทัดสุดท้ายลบออก" บรรทัดอื่น ๆ จะถูกพิมพ์เนื่องจากเป็นsedพฤติกรรมเริ่มต้น

คุณสามารถโยงมันเข้าด้วยกันเพื่อลบหลายบรรทัด

sed '$d' input.txt | sed '$d' | sed '$d'

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

คุณสามารถดูคำตอบเพิ่มเติมได้ที่: https://stackoverflow.com/questions/13380607/how-to-use-sed-to-remove-last-n-lines-of-a-file

นี่คือหนึ่งซับที่ดัดแปลงมาจากหนึ่งในรายการโปรดของฉันที่นั่น:

N=10
sed -n -e ':a' -e "1,$N!{P;N;D;};N;ba"

ฉันสนุกกับการถอดรหัสอันนั้นและฉันก็หวังว่าคุณก็ทำได้เช่นกัน (: มันจะทำการบัฟเฟอร์Nในขณะที่ทำการสแกน แต่ก็มีประสิทธิภาพพอสมควร


3

ฉันอยากรู้ว่าทำไมคุณคิดว่าheadไม่ใช่ตัวเลือก:

~$ man head
...
-n, --lines=[-]K
        print the first K lines instead of the first 10; 
        with the leading `-', print all but the last K lines of each file

สิ่งนี้ดูเหมือนจะสอดคล้องกับวัตถุประสงค์ของคุณตัวอย่างเช่น:

head -n -20 yourfile.txt

5
โปรดทราบว่าสิ่งนี้ใช้ได้กับ GNU headเท่านั้น BSD headไม่มีตัวเลือกนี้ดังนั้นคำตอบนี้จะไม่สามารถใช้กับ Solaris หรือ Unixes อื่น ๆ ที่ไม่มี coreutils ของ GNU OP ติดแท็กสิ่งนี้ด้วย Unix และ Unix-Utils ด้วย
slhck

2
@slhck ไม่ต้องพูดถึงความจริงที่ว่า OP กล่าวถึงสิ่งนี้สำหรับ Solaris
CVN

น่าเสียดายที่มีคนลบการกล่าวถึง Solaris ของฉัน แต่ฉันควรจะพูดถึงต่อไปว่ารุ่นหัวไม่รองรับ
Hans-Peter Störr

1
ขอโทษทุกคน ไม่ได้สังเกตเห็น Solaris และฉันไม่ได้ตระหนักถึงรุ่นต่าง ๆ ของหัว
Anders R. Bystrup

1
@hstoerr Solaris ขณะนี้อยู่ในแท็กของคุณ :)
slhck

0

อีกวิธีหนึ่งที่จะทำหากtail -nไม่รับข้อโต้แย้งเชิงลบก็คือ

tac file.txt | tail -n +6 | tac

สิ่งนี้จะลบ 5 บรรทัดสุดท้าย


ขอบคุณ! นั่นเป็นความคิดที่ดีที่ไม่มีใครมาถึงด้วย น่าเสียดายที่มันค่อนข้างไม่มีประสิทธิภาพสำหรับ usecase ที่ฉันมีในใจกับคำถามนี้: ถ้ามันเป็นไฟล์ขนาดใหญ่มันจะไม่เพียงอ่านอย่างสมบูรณ์ผ่านหนึ่งหรือหลายครั้งเช่นเดียวกับโซลูชั่นอื่น ๆ แต่มันอาจจะเขียนถึง ดิสก์เป็นไฟล์ชั่วคราวโดย tac หากไม่เหมาะสมกับหน่วยความจำ
Hans-Peter Störr

@ Hans-Peter จริงมาก ตัดสินใจที่จะเขียนสคริปต์ python3 ลองใช้github.com/atw31337/donkeyนี้ ฉันแนะนำให้ใช้ตัวเลือกการแสดงผล มันทำงานเร็วกว่าการใช้การเปลี่ยนเส้นทาง
atw31337

เขียนอย่างดี! อย่างไรก็ตามมันจะอ่านไฟล์สองครั้งซึ่งไม่จำเป็นจริงๆถ้าคุณบัฟเฟอร์บรรทัด n สุดท้ายและนี่เป็นปัญหาสำหรับไฟล์ขนาดใหญ่ โดยส่วนตัวแล้วฉันไม่ต้องการสิ่งนั้นอีกต่อไป แต่ในกรณีที่คุณสนุกกับการปรับปรุงและคนอื่น ๆ ต้องการมัน ... หลังจากนั้นมีไลค์และบุ๊กมาร์กคำถาม
Hans-Peter Störr

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

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