วิธีการทำให้คำสั่ง 'ตัด' ปฏิบัติต่อตัวคั่นลำดับเดียวกับเดียว?


309

ฉันกำลังพยายามแยกฟิลด์ (ที่สี่) จากคอลัมน์สตรีมข้อความที่ปรับตามพื้นที่ ฉันพยายามใช้cutคำสั่งในลักษณะดังต่อไปนี้:

cat text.txt | cut -d " " -f 4

น่าเสียดายที่cutไม่ใช้ช่องว่างหลายช่องเป็นตัวคั่นเดียว ฉันสามารถส่งผ่าน awk ได้

awk '{ printf $4; }'

หรือ sed

sed -E "s/[[:space:]]+/ /g"

เพื่อยุบช่องว่าง แต่ฉันต้องการทราบว่ามีวิธีจัดการกับcutตัวคั่นหลายตัวหรือไม่



คำตอบ:


546

ลอง:

tr -s ' ' <text.txt | cut -d ' ' -f4

จากtrหน้าคน:

-s, - squeeze-repeats แทนแต่ละลำดับการป้อนข้อมูลของตัวละครซ้ำ
                        ที่อยู่ในรายการ SET1 ที่มีเหตุการณ์เดียว
                        ของตัวละครนั้น

24
ไม่จำเป็นสำหรับcatที่นี่ คุณสามารถส่งผ่านโดยตรงไปยัง< text.txt en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cattr
arielf

1
ไม่แน่ใจว่ามันเป็นอะไรที่ง่ายกว่า แต่คุณกำลังจะรวมคุณสามารถละทิ้งการตัด-dและแปลโดยตรงจากตัวละครหลาย ๆ แท็บ ตัวอย่างเช่นฉันมาที่นี่เพื่อหาวิธีในการส่งออกการแสดงผลของฉันโดยอัตโนมัติ:who am i | tr -s ' ()' '\t' | cut -f5
Leo

สิ่งนี้ไม่ได้ลบช่องว่างนำหน้า / ต่อท้าย (ซึ่งอาจต้องการหรือไม่ต้องการ แต่โดยปกติแล้วไม่ใช่) ในทางตรงกันข้ามกับโซลูชัน awk วิธีการแก้ปัญหา awk ยังอ่านได้มากขึ้นและ verbose น้อยลง
n.caillou

-1 คำเตือน: นี่ไม่ใช่สิ่งเดียวกันกับการรักษาตัวลบลำดับโดยรวม เปรียบเทียบecho "a b c" | cut -d " " -f2-,echo "a b c" | tr -s " " | cut -d " " -f2-
user541686

96

ในขณะที่คุณแสดงความคิดเห็นในคำถามของคุณawkเป็นวิธีที่จะไป ที่จะใช้cutเป็นไปได้พร้อมกับtr -sการบีบช่องว่างตามคำตอบของเคฟแสดงให้เห็น

ให้ฉันผ่านชุดค่าผสมที่เป็นไปได้ทั้งหมดสำหรับผู้อ่านในอนาคต คำอธิบายอยู่ที่ส่วนการทดสอบ

tr | ตัด

tr -s ' ' < file | cut -d' ' -f4

awk

awk '{print $4}' file

ทุบตี

while read -r _ _ _ myfield _
do
   echo "forth field: $myfield"
done < file

sed

sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' file

การทดสอบ

รับไฟล์นี้มาทดสอบคำสั่งกันเถอะ:

$ cat a
this   is    line     1 more text
this      is line    2     more text
this    is line 3     more text
this is   line 4            more    text

tr | ตัด

$ cut -d' ' -f4 a
is
                        # it does not show what we want!


$ tr -s ' ' < a | cut -d' ' -f4
1
2                       # this makes it!
3
4
$

awk

$ awk '{print $4}' a
1
2
3
4

ทุบตี

นี่จะอ่านฟิลด์ตามลำดับ โดยการใช้_เราระบุว่านี่เป็นตัวแปร Throwaway เป็น "ตัวแปรขยะ" เพื่อละเว้นฟิลด์เหล่านี้ ด้วยวิธีนี้เราเก็บ$myfieldเป็นฟิลด์ที่ 4 ในไฟล์ไม่ว่าจะมีช่องว่างอยู่ระหว่างนั้นหรือไม่

$ while read -r _ _ _ a _; do echo "4th field: $a"; done < a
4th field: 1
4th field: 2
4th field: 3
4th field: 4

sed

([^ ]*[ ]*){3}นี้จับสามกลุ่มของช่องว่างและไม่มีช่องว่างด้วย จากนั้นจะจับอะไรก็ตามมาจนพื้นที่ที่เป็นเขตที่ 4 \1ที่ว่ามันจะถูกพิมพ์สุดท้ายกับ

$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4

2
awkไม่เพียง แต่สง่างามและเรียบง่าย แต่ยังรวมอยู่ใน VMware ESXi ซึ่งtrหายไป
121391

2
@ user121391 ยังมีอีกเหตุผลที่จะใช้awk!
fedorqui 'ดังนั้นหยุดการทำร้าย'

@fedorqui ฉันไม่เคยได้ยินเครื่องหมายขีดล่างเป็น "ตัวแปรขยะ" คุณสามารถให้ข้อมูลเชิงลึก / อ้างอิงเพิ่มเติมเกี่ยวกับเรื่องนี้ได้หรือไม่
BryKKan

1
@BryKKan ฉันเรียนรู้เกี่ยวกับมันใน Greg ฉันจะอ่านไฟล์ (data stream, variable) ทีละบรรทัด (และ / หรือ field-by-field) ได้อย่างไร? : บางคนใช้ตัวแปร throwaway _ เป็น "ตัวแปรขยะ" เพื่อละเว้นฟิลด์ มัน (หรือตัวแปรใด ๆ ) สามารถใช้งานได้มากกว่าหนึ่งครั้งในreadคำสั่งเดียวถ้าเราไม่สนใจสิ่งที่เกิดขึ้น มันสามารถเป็นอะไรก็ได้มันเป็นเพียงแค่ว่ามันกลายเป็นมาตรฐานแทนjunk_varหรือwhatever:)
fedorqui 'ดังนั้นหยุดการทำร้าย'

25

ทางออกที่สั้นที่สุด / เป็นมิตร

หลังจากที่กลายเป็นผิดหวังกับมากเกินไปข้อ จำกัด ของcutผมเขียนทดแทนของตัวเองซึ่งผมเรียกว่าcutsสำหรับ "ตัดเตียรอยด์"

การตัดให้สิ่งที่น่าจะเป็นทางออกที่ง่ายที่สุดสำหรับปัญหานี้และอีกหลายปัญหาที่เกี่ยวข้องกับการตัด / วาง

ตัวอย่างหนึ่งจากหลาย ๆ คนที่ตอบคำถามนี้โดยเฉพาะ:

$ cat text.txt
0   1        2 3
0 1          2   3 4

$ cuts 2 text.txt
2
2

cuts สนับสนุน:

  • การตรวจจับตัวคั่นฟิลด์ที่พบบ่อยที่สุดโดยอัตโนมัติในไฟล์ (+ ความสามารถในการแทนที่ค่าเริ่มต้น)
  • การจับคู่แบบหลายตัวอักษรแบบผสมถ่านและแบบ regex
  • แยกคอลัมน์จากหลายไฟล์ด้วยตัวคั่นผสม
  • ออฟเซ็ตจากจุดสิ้นสุดของบรรทัด (ใช้จำนวนลบ) นอกเหนือจากจุดเริ่มต้นของบรรทัด
  • การวางคอลัมน์แบบด้านต่อด้านโดยอัตโนมัติ (ไม่จำเป็นต้องเรียกpasteแยกต่างหาก)
  • สนับสนุนการจัดลำดับฟิลด์ใหม่
  • ไฟล์กำหนดค่าที่ผู้ใช้สามารถเปลี่ยนการตั้งค่าส่วนตัวของพวกเขา
  • เน้นที่ความเป็นมิตรกับผู้ใช้และการพิมพ์ที่ต้องการความเรียบง่าย

และอีกมากมาย cutไม่มีที่ให้บริการโดยมาตรฐาน

ดูเพิ่มเติมที่: https://stackoverflow.com/a/24543231/1296044

แหล่งที่มาและเอกสารประกอบ (ซอฟต์แวร์ฟรี): http://arielf.github.io/cuts/


4

Perl one-liner แสดงให้เห็นว่า Perl เกี่ยวข้องกับ awk อย่างไร

perl -lane 'print $F[3]' text.txt

อย่างไรก็ตาม@Fอาร์เรย์ autosplit เริ่มต้นที่ดัชนี$F[0]ในขณะที่ awk เขตข้อมูลเริ่มต้นด้วย$1


3

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

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