ฉันควรใช้อะไรเมื่อตัดไม่ได้?


19

ฉันมีไฟล์citiesเช่นนี้:

[1598] San Diego, US (inactive)
[4517] St Louis, US (inactive)
[6346] Orlando, US (inactive)

ฉันต้องการตัดชื่อเมืองออกเพื่อที่ฉันจะได้:

San Diego
St Louis
Orlando

นี่คือสิ่งที่ดีที่สุดที่ฉันสามารถทำได้:

cut -d ',' -f1 cities | cut -d ']' -f2

แต่นั่นยังทำให้ฉันมีช่องว่างหน้าชื่อ มีcutคำสั่ง like ที่ฉันสามารถใช้ที่รับตัวคั่นของอักขระหลายตัวเพื่อให้ฉันสามารถตัดต่อได้]หรือไม่?


1
trมีประโยชน์สำหรับการลบอักขระที่คุณไม่ต้องการ
LawrenceC

หากคุณลองใช้รหัสในคำตอบของผู้คนคุณจะเห็นผลลัพธ์ที่แตกต่างกันสามรายการ สิ่งนี้แสดงให้เห็นคำถามของคุณไม่ชัดเจน 100% "ตัดออก" หมายถึงลบหรือเลือกหรือไม่ คุณต้องการ(inactive)สถานะหรือไม่? โปรดระบุตัวอย่างผลลัพธ์
มิเคล

@Mikel - เมื่อพิจารณาว่าฉันใช้cutเพื่อตัดสิ่งต่าง ๆ ออกและคุณสามารถเห็นเจตนาของตัวอย่างที่ล้มเหลวที่ฉันมีมันควรจะค่อนข้างชัดเจนในบริบท ฉันจะให้ตัวอย่างออกมาเพื่อล้างมันให้ไกลขึ้น :)
Kit Sunde

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

1
@Kit Sunde: ด้วยผลลัพธ์ตัวอย่างจะเข้าใจได้อย่างแน่นอน ชื่อน่ารัก "ตัดออก" ทำให้ฉันคิดว่าจะเกิดอะไรขึ้นเมื่อคุณกด Ctrl + X ซึ่งเป็นสาเหตุที่ฉันเสนอการเปลี่ยนแปลง แต่เป็นคำถามของคุณ Downvoting จะไร้สาระเมื่อมันเป็นเพียงความขัดแย้งที่เรียบง่าย
มิเคล

คำตอบ:


15

Awk (ตรวจสอบข้อมูล Awk ด้วย ) สวยงามด้วยคำถามแบบนั้น ลอง:

awk -F'[],] *' '{print $2}' cities

สิ่งนี้จะกำหนดตัวคั่นฟิลด์-Fเป็น[],] *- ซึ่งหมายถึงการเกิดขึ้นครั้งเดียวของวงเล็บเหลี่ยมปิดหรือเครื่องหมายจุลภาคตามด้วยศูนย์หรือจำนวนช่องว่างใด ๆ แน่นอนคุณสามารถเปลี่ยนสิ่งนั้นให้เหมาะสมกับความต้องการได้ อ่านค่าในนิพจน์ทั่วไป

เมื่อแบ่งบรรทัดแล้วคุณสามารถทำสิ่งที่คุณต้องการด้วยผลการแยก print $2นี่ฉันตัดสินใจที่จะพิมพ์ออกฟิลด์ที่สองเท่านั้นที่มี โปรดทราบว่ามันเป็นสิ่งสำคัญที่จะใช้เครื่องหมายคำพูดเดี่ยวรอบคำสั่ง awk มิฉะนั้น $ 2 จะถูกแทนที่ด้วยเชลล์


2
]ไม่ใช่วงเล็บเหลี่ยม <>วงเล็บมุมเป็น []คือ "วงเล็บเหลี่ยม" หรือเพียงแค่ "วงเล็บเหลี่ยม"
cjm

ฉันคิดว่าคุณจำเป็นต้องหลบเลี่ยงวงเล็บปิดนั้นเว้นแต่ฉันจะต้องอ่านคำอธิบายปกติของฉัน
Kit Sunde

@cjm - บางทีเขาเป็นคนเยอรมัน: news.ycombinator.com/item?id=1181243 :)
Kit Sunde

1
@cjm ขอโทษฉันหมายถึงการพูดวงเล็บเหลี่ยมพิมพ์เร็วเกินไปเล็กน้อย @ คิทฉันไม่ใช่คนเยอรมัน คุณไม่ต้องการหนีวงเล็บปิดด้านใน (มันจะไม่มีจุดประสงค์) แต่ต้องเป็นอักขระตัวแรกในช่วง
asoundmove

12

คุณสามารถแก้ไขล่าสุดcutในไปป์ไลน์ของคุณเป็น:

cut -d ' ' -f2-

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

cut -d ',' -f1 cities | cut -d ' ' -f2-

12

สำหรับการวิเคราะห์คำที่ซับซ้อนยิ่งขึ้นคุณควรใช้sed (1) :

sed -e 's/\[[0-9]\+\] \([^,]\+\),.*/\1/' cities

หรือใช้-rเพื่อลดความซับซ้อนของการแสดงออกปกติตามที่แนะนำโดยpepoluan :

sed -re 's/\[[0-9]+\] ([^,]+),.*/\1/' cities

2
+1 คุณยังสามารถใช้ -r เพื่อป้องกันการหลบหลีกตัวอักษร regex ขั้นสูงทำให้รูปแบบ regex ง่ายขึ้นมาก
pepoluan

0

ปกติฉันจะใช้ Perl เมื่อสิ่งต่าง ๆ ยากเกินกว่าจะล่อลวงและตะไคร่

มีหลายวิธีที่คุณสามารถเขียนเป็น Perl ได้ ตัวอย่างเช่นคุณอาจต้องการให้เร็วหรือคุณอาจต้องการจัดการกับปัญหาที่ไม่คาดคิดเล็กน้อยในอินพุต (เช่นสองช่องว่างที่คาดว่าจะมี)

วิธีหนึ่งที่ชัดเจน (สมมติว่า id คือตัวเลขเมืองเป็นตัวอักษรสถานะเป็นตัวอักษร):

while (<>) {
    if (/^\[\d+\] (\w+(?: \w+)*), \w+ \(\w*\)$/) {
        my $city = $1;
        print "$city\n";
    }
}

หรือช้าลง แต่ได้รับอนุญาตมากขึ้น (ทำ backtracking มากขึ้น):

while (<>) {
    if (/^.*\]\s+(.*),.*$/) {
        my $city = $1;
        print "$city\n";
    }
}

หรือเร็วกว่า (ฟิลด์หยุดเมื่อเกิดวงเล็บปิดครั้งแรก):

while (<>) {
    if (/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/) {
        my $city = $1;
        print "$city\n";
    }
}

จากบรรทัดคำสั่งมากกว่าสคริปต์คุณสามารถใช้-nตัวเลือกซึ่งโดยทั่วไปจะเพิ่มwhile (<>) { BLOCK }วง:

perl -ne '/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/ and print $1, "\n";' cities

หรือถ้าคุณต้องการให้การใช้งานมีลักษณะคล้ายกับการตัดคุณสามารถใช้-Fตัวเลือกซึ่งคล้ายกับ-Fตัวเลือกของ awk ตัวอย่างเช่น:

perl -a -n -F'/[],]\s+/' -e 'print $F[1], "\n"' cities

วิธีนี้ถือว่าชัดเจนว่าไม่มีฟิลด์ใดที่จะมีตัวคั่นใด ๆ

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