วิธีลบคอลัมน์สุดท้ายของไฟล์ใน Linux


25

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

ตัวอย่าง:

การป้อนข้อมูล:

1223 1234 1323 ... 2222 123
1233 1234 1233 ... 3444 125
0000 5553 3455 ... 2334 222

และฉันต้องการให้ผลลัพธ์ของฉันเป็น:

1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

มีหลายวิธีในการทำเช่นนี้ .. โปรดเพิ่มตัวอย่างและเอาท์พุทที่คุณคาดหวังไว้จากมัน ..
heemayl

@heemayl ok ฉันไม่
Zara

ขอบคุณ .. มีการแยกแท็บคอลัมน์หรือเว้นวรรคแล้วหรือยัง
heemayl

@heemayl space เป็น deliminator
zara

คำตอบ:


43

ด้วยawk:

awk 'NF{NF-=1};1' <in >out

หรือ:

awk 'NF{NF--};1' <in >out

หรือ:

awk 'NF{--NF};1' <in >out

แม้ว่ามันจะดูเหมือนของวูดู แต่ก็ใช้ได้ มีสามส่วนสำหรับแต่ละคำสั่ง awk เหล่านี้

สิ่งแรกคือNFซึ่งเป็นเงื่อนไขเบื้องต้นสำหรับส่วนที่สอง NFเป็นตัวแปรที่มีจำนวนฟิลด์ในบรรทัด ใน AWK สิ่งที่จริงถ้าพวกเขาไม่ได้เป็น 0 ""หรือสตริงที่ว่างเปล่า ดังนั้นส่วนที่สอง (โดยที่NFลดลง) จะเกิดขึ้นถ้าNFไม่ใช่ 0

ส่วนที่สอง (อย่างใดอย่างหนึ่งNF-=1 NF--หรือ--NF) เป็นเพียงการลบหนึ่งจากNFตัวแปร สิ่งนี้จะป้องกันไม่ให้มีการพิมพ์ฟิลด์สุดท้ายเนื่องจากเมื่อคุณเปลี่ยนฟิลด์ (ลบฟิลด์สุดท้ายในกรณีนี้) ให้awkสร้างใหม่$0เชื่อมต่อทุกฟิลด์โดยคั่นด้วยช่องว่างตามค่าเริ่มต้น $0ไม่มีฟิลด์สุดท้ายอีกต่อไป

1ส่วนสุดท้ายคือ trueมันไม่ได้วิเศษก็ใช้เช่นเดียวกับการแสดงออกที่หมายถึง หากมีการawkประเมินการแสดงออกให้เป็นจริงโดยไม่มีการกระทำใด ๆ ที่เกี่ยวข้องดำเนินการเริ่มต้นคือawkprint $0


@JJoao: อ่าขอบคุณลืมไป--แล้ว หมายเหตุในปัจจุบันคุณต้องการ;1POSIX ที่เข้ากันได้
cuonglm

สัญชาตญาณเริ่มต้นของฉันคือการใช้ลูป for แต่มันกระชับและฉลาดกว่ามาก
Sergiy Kolodyazhnyy

5
เป็นที่น่าสังเกตว่าหากคุณใช้ตัวคั่นที่ไม่ใช่ค่าเริ่มต้นคุณจะต้องทำการเปลี่ยนแปลงบางอย่าง สมมติว่า,เป็นตัวคั่นของคุณ:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
นาย Llama

1
ผลของการลด NF คือพฤติกรรมที่ไม่ได้กำหนดโดย POSIX - คุณจะได้รับเอาต์พุตที่แตกต่างกันขึ้นอยู่กับว่าคุณใช้ awk อะไร awks บางตัวจะลบฟิลด์สุดท้ายตามที่คุณต้องการบางอันจะไม่ทำอะไรเลยและคนอื่น ๆ สามารถรายงานข้อผิดพลาดทางไวยากรณ์หรือสิ่งอื่นใดก็ได้
Ed Morton

16

ใช้grepกับ PCRE:

$ grep -Po '.*(?=\s+[^\s]+$)' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

ใช้ GNU sed:

$ sed -r 's/(.*)\s+[^\s]+$/\1/' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

1
@ramin Sure..could ที่คุณโปรดถามว่ามันเป็นคำถามใหม่ (นี่คือวิธีการที่เว็บไซต์นี้ทำงาน) :)
heemayl

@ramin มันให้คุณ จำกัด เวลาหรือคำเตือนใด ๆ ?
heemayl

มันบอกว่านี่เป็นคำถามที่ไม่ได้มาตรฐาน!
ร่า

@ramin ตกลง .. ให้ฉันติดต่อผู้ดูแลระบบเป็นไปได้ไหมว่าพวกเขาสามารถช่วยคุณได้ .. btw คุณตรวจสอบ QA เก่า ๆ เกี่ยวกับคำถามของคุณหรือไม่? ความเป็นไปได้ว่าคำถามคือแล้วถามและตอบ ..
heemayl

3
อย่าถามคำถามพื้นฐานขั้นสูงเช่น " ฉันจะเปลี่ยนชื่อไฟล์ใน Linux ได้อย่างไร " ใช้ Google
Christoffer Hammarström



1

หากตัวคั่นเป็นอักขระตัวเดียวเสมอ (ดังนั้นตัวคั่นต่อเนื่องสองตัวหรือมากกว่านั้นกำหนดเขตข้อมูลว่างเปล่า) คุณสามารถheadบรรทัดแรกจากไฟล์อินพุตของคุณนับตัวคั่น ( nตัวคั่นหมายถึงจำนวนเขตข้อมูลn+1) จากนั้นใช้cutเพื่อพิมพ์จาก1ฟิลด์ st สูงสุดถึงnฟิลด์ th (ที่สองถึงที่สุดท้าย) เช่นมีการป้อนข้อมูลที่คั่นด้วยแท็บ:

n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l)
cut -f1-$n infile > outfile

หรือเช่นกับไฟล์ csv :

n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l)
cut -d, -f1-$n infile > outfile

ฉันจะใช้การวัดประสิทธิภาพในภายหลังหากฉันมีเวลา แต่ด้วยข้อมูลจำนวนมากฉันคิดว่าโซลูชันนี้ควรเร็วกว่าโซลูชันอื่น ๆ ที่ใช้ regex เนื่องจากการประมวลผลนี้น้อยที่สุดในบรรทัดแรกเพื่อรับหมายเลข ของเขตข้อมูลและจากนั้นใช้cutซึ่งปรับให้เหมาะสมสำหรับงานนี้



0

ใช้เป็นกลุ่ม:

เปิดไฟล์เป็นกลุ่ม

vim <filename> 

ไปที่แถวแรกในกรณีที่วางเคอร์เซอร์ไว้ที่อื่น

gg

สร้างแมโครชื่อ "q" qqซึ่งไปที่ด้านหลังของบรรทัดปัจจุบัน$จากนั้นกลับไปที่ช่องว่างสุดท้ายF(ตัวอักษร F ตามด้วย SPACE ตามตัวอักษร) จากนั้นลบจากตำแหน่งปัจจุบันจนถึงจุดสิ้นสุดของบรรทัดDลงไปที่บรรทัดถัดไปjและ qหยุดการบันทึกแมโครด้วย

qq$F Djq

ตอนนี้เราสามารถทำซ้ำแมโครของเรากับ@qแต่ละบรรทัด
นอกจากนี้เรายังสามารถกด@@เพื่อทำซ้ำแมโครสุดท้ายหรือทำได้ง่ายยิ่งขึ้น:

99@q

เพื่อทำซ้ำมาโคร 99 ครั้ง
หมายเหตุ: หมายเลขจะต้องไม่ตรงกับเส้นทุกประการ


0

สำหรับผู้ที่มีปัญหาคล้ายกัน แต่มีตัวคั่นฟิลด์ต่างกันawkวิธีนี้จะรักษาตัวคั่นฟิลด์ไว้อย่างถูกต้อง:

$ cat file 
foo.bar.baz
baz.bar.foo
$ awk -F'.' 'sub(FS $NF,x)' file
foo.bar
baz.bar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.