ใช้พื้นที่เป็นตัวคั่นด้วยคำสั่ง cut


328

ฉันต้องการใช้พื้นที่เป็นตัวคั่นด้วยcutคำสั่ง

ฉันสามารถใช้ไวยากรณ์ใดในเรื่องนี้


42
ไม่จริงหน้า man for cut ไม่ได้อธิบายสิ่งนี้และโดยทั่วไปไม่ใช่ข้อมูล
UncleZeiv

2
นอกจากนี้ "การตัดข้อมูล" ก็ไม่ได้รับการปรับปรุงในกรณีนี้
cardiff space man

3
@ mklement0 หากฉันจำได้ว่าฉันตอบกลับความคิดเห็นที่ถูกลบไปแล้วซึ่งเป็นการยกเลิกคำถามนี้ว่าได้รับคำตอบในหน้าคนซึ่งอยู่ในความเห็นของฉัน "ไม่จริง" ไม่ว่าจะมีเหตุผลที่ดีก็ตาม หรือไม่ - ตอนนี้ในขณะที่ฉันยอมรับว่าอาจมีเหตุผลที่ดีสำหรับการขาดข้อมูลนี้ฉันยังคงคิดว่าเอกสารที่ไม่มีตัวอย่างการใช้งานทั่วไปมักจะเกิดความรำคาญอย่างน้อยที่สุดเมื่อไม่ไร้ประโยชน์ทันที
UncleZeiv

3
@ UncleZeiv เข้าใจแล้ว ขอบคุณสำหรับการชี้แจง ด้วยความสนใจในคำถามนี้มันยุติธรรมที่จะถือว่าmanหน้านั้นไม่เพียงพอ ลองดู: " -d delimใช้delimเป็นอักขระตัวคั่นฟิลด์แทนอักขระแท็บ" (BSD cutแต่รุ่น GNU และ POSIX สเป็คค่อนข้างมากเหมือนกัน) ใช้เปลือกเพื่อเรียกcut- กรณีทั่วไป - ดังนั้นคุณจะต้องรู้วิธีการโดยทั่วไปผ่านพื้นที่เป็นอาร์กิวเมนต์ใช้ไวยากรณ์เปลือกซึ่งเป็นเนื้อหาที่ไม่ได้เป็นcutงานหน้าของมนุษย์ ตัวอย่างในโลกแห่งความจริงช่วยได้อย่างไรและหน้าGNUจะขาดมัน
mklement0

4
แม้ว่าคำตอบที่เลือกนั้นถูกต้องทางเทคนิคให้พิจารณาการเลือกคำตอบที่ใหม่กว่าและครอบคลุมโดย @ mklement0 เป็นคำตอบที่ได้รับการยอมรับเพื่อให้กรองไปด้านบน
David LeBauer

คำตอบ:


367
cut -d ' ' -f 2

โดยที่ 2 คือหมายเลขฟิลด์ของฟิลด์ที่คั่นด้วยช่องว่างที่คุณต้องการ


2
คุณสามารถบอกให้ cut ใช้ตัวอักขระจำนวนหนึ่งเป็นตัวคั่นได้เช่นเดียวกับใน RegEx เช่นจำนวนช่องว่างใด ๆ เช่น \ s +
สะเทินน้ำสะเทินบก

3
@foampile ไม่ฉันไม่เชื่อว่าคุณทำได้
Jonathan Hartley

6
คุณไม่สามารถใช้ regexes ด้วยcutแต่คุณสามารถcutsพยายามที่จะ "แก้ไข" cutข้อ จำกัดทั้งหมด: github.com/arielf/cuts
arielf

คุณจะได้รับฟิลด์ที่ถูก จำกัด พื้นที่ที่สามทุกครั้งหรือไม่ ชอบcut -d ' ' -f 3,6,9,12,15,18โดยไม่ต้องระบุทุกหมายเลข?
Monocito

169

โดยปกติถ้าคุณใช้ช่องว่างเป็นตัวคั่นคุณต้องการใช้ช่องว่างหลายช่องเป็นช่องเดียวเนื่องจากคุณแยกวิเคราะห์เอาต์พุตของคำสั่งที่จัดแนวคอลัมน์บางคอลัมน์ให้มีช่องว่าง (และ google ค้นหาสิ่งที่นำฉันมาที่นี่)

ในกรณีนี้cutคำสั่งเดียวไม่เพียงพอและคุณต้องใช้:

tr -s ' ' | cut -d ' ' -f 2

หรือ

awk '{print $2}'

2
ขอบคุณสำหรับการใช้งานตัวอย่าง awk สิ่งที่ฉันต้องการ
spazm

44

เพื่อเติมเต็มคำตอบที่มีอยู่และเป็นประโยชน์; tip of the hat to QZ ฝ่ายสนับสนุนที่สนับสนุนให้ฉันโพสต์คำตอบแยกต่างหาก:

มีกลไกที่แตกต่างกันสองแบบมาที่นี่:

  • (ก) ว่าcut ตัวเองต้องใช้ตัวคั่น (พื้นที่ในกรณีนี้) ส่งผ่านไปยัง-dตัวเลือกที่จะเป็นข้อโต้แย้งที่แยกจากกันหรือไม่ว่าจะเป็นที่ยอมรับในการผนวกโดยตรง-dเพื่อ

  • (b) วิธีที่เชลล์แยกวิเคราะห์อาร์กิวเมนต์ก่อนส่งผ่านไปยังคำสั่งที่เรียกใช้

(a) ตอบโดยอ้างจากแนวทาง POSIX สำหรับสาธารณูปโภค (เหมืองเน้น)

หากการสรุปโดยย่อของยูทิลิตี้มาตรฐานแสดงตัวเลือกที่มีตัวเลือกบังคับ - อาร์กิวเมนต์ [... ] แอปพลิเคชันที่สอดคล้องกันจะต้องใช้อาร์กิวเมนต์แยกต่างหากสำหรับตัวเลือกนั้นและตัวเลือกอาร์กิวเมนต์ของมัน อย่างไรก็ตามการดำเนินงานตามนโยบายจะยังอนุญาตให้มีการประยุกต์ใช้เพื่อระบุตัวเลือกและตัวเลือกการโต้แย้งในสตริงอาร์กิวเมนต์เดียวกันโดยไม่ต้องแทรกแซงตัวอักษร

ในคำอื่น ๆ : ในกรณีนี้เพราะ-d's ตัวเลือกอาร์กิวเมนต์เป็นบังคับ , คุณสามารถเลือกได้ว่าจะระบุตัวคั่นเป็น :

  • (s) EITHER: อาร์กิวเมนต์ที่แยกต่างหาก
  • (ง) หรือ: เป็นค่าที่แนบมาโดยตรง-dเพื่อ

เมื่อคุณเลือก (s) หรือ (d) มันคือการแยกสตริงตัวอักษรของเชลล์ - (b) - ที่สำคัญ:

  • ด้วยวิธีการ(s) , ทุกรูปแบบต่อไปนี้จะเทียบเท่า:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • ด้วยวิธีการ(d)ทุกรูปแบบต่อไปนี้เทียบเท่า:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

การอธิบายความเท่าเทียมกันโดยการประมวลผลแบบสตริงของเชลล์ :

การแก้ปัญหาcutทั้งหมดข้างต้นส่งผลให้เกิดสตริงที่แน่นอน (ในแต่ละกลุ่ม) ตามเวลาที่เห็น :

  • (s) : cutเห็นว่า-dเป็นอาร์กิวเมนต์ของตัวเองตามด้วยอาร์กิวเมนต์แยกต่างหากที่มีช่องว่างถ่าน - โดยไม่มีเครื่องหมายคำพูดหรือ\คำนำหน้า!

  • (d) : cutเห็น-d พร้อมถ่านอวกาศ - ไม่มีคำพูดหรือ\คำนำหน้า! - เป็นส่วนหนึ่งของอาร์กิวเมนต์เดียวกัน

เหตุผลที่รูปแบบในกลุ่มที่เกี่ยวข้องในท้ายที่สุดเหมือนกันคือสองเท่าขึ้นอยู่กับวิธีที่เชลล์แยกวิเคราะห์ตัวอักษรสตริง :

  • เชลล์อนุญาตให้ระบุตัวอักษรตามที่เป็นอยู่ผ่านกลไกที่เรียกว่าquotingซึ่งสามารถมีได้หลายรูปแบบ :
    • สตริงที่ยกมาเดี่ยว : เนื้อหาภายใน'...'จะถูกนำตัวอักษรและรูปแบบอาร์กิวเมนต์เดียว
    • สตริงที่มีเครื่องหมายคำพูดคู่ : เนื้อหาภายใน"..."ยังเป็นอาร์กิวเมนต์เดี่ยวแต่อยู่ภายใต้การแก้ไข (ขยายการอ้างอิงตัวแปรเช่นการ$varแทนที่คำสั่ง ( $(...)หรือ`...`) หรือการขยายเลขคณิต ( $(( ... )))
    • \- การอ้างถึงอักขระแต่ละตัว : อักขระที่อยู่\ก่อนหน้าทำให้อักขระนั้นถูกตีความว่าเป็นตัวอักษร
  • อ้างจะสมบูรณ์โดยการกำจัดอ้างซึ่งหมายความว่าเมื่อเปลือกได้แยกวิเคราะห์บรรทัดคำสั่งก็เอาตัวละครที่อ้างจากการขัดแย้ง (การปิดล้อม'...'หรือ"..."หรือ\อินสแตนซ์) - จึงถูกคำสั่งเรียกไม่เคยเห็นตัวละครพูด

36

คุณสามารถพูดได้ว่า:

cut -d\  -f 2

โปรดทราบว่ามีช่องว่างสองช่องหลังจากแบ็กสแลช


30
คนที่รู้ว่า '\' จะหลบหนีตัวละครตัวต่อไปจะต้องระมัดระวังเป็นอย่างยิ่งที่จะทราบว่าสิ่งใดเกิดขึ้น การใช้ '\' เพื่อหลบหนีอักขระอวกาศเช่นนี้เป็นสำนวนที่พบบ่อยมาก
โจนาธานฮาร์ทลี่

3
@ Jonathan Hartley กันมากที่สุดของรหัสที่อ่านไม่ได้แน่นอน :)
Luca Borrione

1
จากมุมมองของ linux / unix \ เป็นความพยายามครั้งแรกของฉันและใช้งานได้ ฉันเห็นว่ามันชัดเจนน้อยกว่าเมื่อเทียบกับ' 'แต่ฉันแน่ใจว่าหลายคนยินดีที่จะอ่านที่นี่เพื่อรับรองพฤติกรรม เพื่อความเข้าใจที่ดีขึ้นโปรดดูความคิดเห็นของ @ mklement0 ด้านล่าง
tresf

แก้ไข @JonathanHartley: "ความเห็นแก่ตัวคนที่รู้ว่า '\' หนีตัวอักษรถัดไปและถือว่าคนอื่นรู้ว่ายัง" สำหรับโครงการส่วนบุคคลสิ่งนี้ไม่ได้ใช้ แต่ในการตั้งค่าทีมการสันนิษฐานนั้นเป็นสิ่งที่อันตรายมาก (และอาจมีค่าใช้จ่ายสูง)
Eduard Nicodei

1
@EduardNicodei โอ้ฉันเห็นด้วย เรากำลังพูดถึงผู้อ่านของรหัส ("ใครสังเกตเห็น ... ?") ไม่ใช่ผู้เขียน แต่ในบางทีมก็ถือว่าดีในระดับหนึ่งของความเชี่ยวชาญ ขึ้นอยู่กับสภาพแวดล้อม
Jonathan Hartley

5

ฉันเพิ่งค้นพบว่าคุณยังสามารถใช้"-d ":

cut "-d "

ทดสอบ

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am

1
อันที่จริง - '-d 'หรือ
mklement0

3
โปรดทราบว่าจากcutมุมมองของทั้งหมดต่อไปนี้จะเหมือนกัน: "-d ", '-d ', -d" ", -d' 'และ-d\<space>ทุกรูปแบบโดยตรงผนวกอาร์กิวเมนต์ตัวเลือก (เว้นวรรค) เพื่อตัวเลือก ( -d) และผลในสายเดียวกันที่แน่นอนตามเวลาที่cutเห็นพวกเขาเป็นหนึ่งเดียว อาร์กิวเมนต์ที่มี d ตามด้วยช่องว่างหลังจากเชลล์ทำการลบ
เครื่องหมาย

1
คำตอบ @ mklement0 ควรจะคำตอบ มันครอบคลุมมากที่สุดในหน้านี้ (แม้ว่ามันจะเป็นความคิดเห็น)
tresf

@QZSupport: ฉันซาบซึ้งในความรู้สึกและกำลังใจ - มันเป็นแรงบันดาลใจให้ฉันโพสต์คำตอบของตัวเองพร้อมข้อมูลพื้นฐานเพิ่มเติม
mklement0

1
การค้นพบที่น่าสนใจฮ่า ๆ !
Harry

4

คุณไม่สามารถตัดได้อย่างง่ายดายหากข้อมูลมีหลายช่องว่างตัวอย่างเช่น ฉันพบว่ามีประโยชน์ในการทำให้อินพุตเป็นมาตรฐานสำหรับการประมวลผลที่ง่ายขึ้น เคล็ดลับหนึ่งคือการใช้ sed สำหรับการทำให้ปกติดังต่อไปนี้

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar

3

scutเป็นยูทิลิตีแบบ cut-like (ฉลาดขึ้น แต่ช้ากว่าฉันทำ) ที่สามารถใช้ Perl regl ใด ๆ เป็นโทเค็นการทำลาย การแบ่งช่องว่างเป็นค่าเริ่มต้น แต่คุณยังสามารถแยกย่อย multi-char regexes ทางเลือก ฯลฯ

scut -f='6 2 8 7' < input.file  > output.file

ดังนั้นคำสั่งดังกล่าวจะทำลายคอลัมน์ในช่องว่างและแยกคอลัมน์ (ตาม 0) 6 2 8 7 ในลำดับที่


0

ฉันมีคำตอบ (ฉันยอมรับคำตอบที่ค่อนข้างสับสน) ซึ่งเกี่ยวข้องกับsedการแสดงออกปกติและการจับภาพกลุ่ม:

  • \S* - คำแรก
  • \s* - ตัวคั่น
  • (\S*) - คำที่สอง - จับภาพ
  • .* - สายที่เหลือ

ในฐานะที่เป็นsedการแสดงออกถึงความต้องการของกลุ่มการจับภาพที่จะหนีออกมาคือและ\(\)

\1ผลตอบแทนสำเนาของกลุ่มที่ถูกจับได้เช่นคำที่สอง

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

เมื่อคุณดูคำตอบนี้มันค่อนข้างสับสนและคุณอาจคิดว่าทำไมต้องกังวล? ฉันหวังว่าบางคนอาจจะไป "อ้า!" และจะใช้รูปแบบนี้เพื่อแก้ปัญหาการแยกข้อความที่ซับซ้อนด้วยsedนิพจน์เดียว

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