ลบจนถึงการเกิดขึ้นครั้งแรกของลำไส้ใหญ่โดยใช้ sed


16

คำสั่ง sed ของฉันคือ

 sed '/(.*:)/d' <<< 'abcd:bcde:cdeaf'

มันจะต้องกลับมา

bcde:cdeaf

(เช่น) ตัวละครทั้งหมดก่อนที่เครื่องหมายโคลอนแรกในบรรทัดและเครื่องหมายโคลอนต้องถูกลบออก

แต่นี่ไม่ได้เป็นการลบอะไรเลย

ความสับสนของฉันส่วนใหญ่เกิดจาก

1) parens สำหรับการจับคู่รูปแบบจำเป็นต้องได้รับการยกเว้นภายใน sed regex-es หรือไม่?

2) ในกรณีใดกรณีหนึ่ง (ด้วยการหลบหนี / ไม่ต้องใช้การหลบหลีก) มันใช้งานไม่ได้ ฉันเหนื่อย,

sed -E '/\\(.*:\\)/d' <<< 'abcd:bcde'
sed 

1
sed 's/[^:]*://'คุณต้องการ และคุณไม่ได้dลบบรรทัดอินพุตโดยวิธีคุณกำลังแก้ไขด้วยs///คำสั่ง ubstitution คุณต้องแทนที่บิตแรกไม่ใช่โคลอนบิตและโคลอนที่ตามหลังโดยไม่มีอะไรเลย
mikeserv

ที่แก้มัน ... ขอบคุณมนุษย์ ... นี่คือตัวอย่างที่ฉันได้เรียนรู้การจับคู่รูปแบบ regex ภายใน sed ... ดังนั้นฉันกำลังมองหาคำตอบที่ใช้จับคู่กลุ่ม / รูปแบบกับ parens ...

3
หรือเพียงแค่ใช้ทุบตี: printf "%s\n" "${line#*:}"...
jasonwryan

1
@ jasonwryan - จุดที่ดีเมื่อพิจารณาจากตัวอย่างแหล่งที่มา มันเป็นวิธีที่มีประสิทธิภาพมากขึ้นในการจัดการมัน แต่ถ้ามันเป็นwhile read lineที่ได้รับ$lineอาจจะsedควรได้รับการแนะนำ
mikeserv

คำตอบ:


23
$ echo 'abcd:bcde:cdeaf' | sed 's/^[^:]*://g'
bcde:cdeaf

วิธีแรก^หมายถึงจุดเริ่มต้นของบรรทัด [^:]เป็นเพียงวิธีเดียวที่ฉันรู้วิธีการเขียนไม่ลำไส้ใหญ่ *หลังจากลำไส้ใหญ่หมายถึงจำนวนของสิ่งใด ๆ ที่เหมาะสมก่อนที่ฉัน (ในกรณีนี้ที่ไม่ลำไส้ใหญ่) ในที่สุดการ:เลือกลำไส้ใหญ่

กล่าวอีกนัยหนึ่งให้เลือกจุดเริ่มต้นของบรรทัดจำนวนของสิ่งที่ไม่ใช่โคลอนและโคลอนแรก

//gวิธีลบทุกกรณีจับคู่


3
คุณไม่จำเป็นต้อง^ยึดการจับคู่ของคุณยกเว้นเพราะคุณเพิ่มการgตั้งค่าสถานะ lobal ด้วย สามารถมีรูปแบบที่เกิดขึ้นครั้งแรกเพียงครั้งเดียวเท่านั้นดังนั้นgแฟล็ก lobal จะไม่ลบ[^:]*:รูปแบบทั้งหมดออกจากบรรทัดตามที่ควรทำหากคุณไม่ได้^ทอดสมอ แทนที่จะสร้างความสับสนให้กับ regex ด้วยค่าสถานะที่ไม่จำเป็นสองค่าเท่านั้นซึ่งจะทำให้เกิดความไม่สมดุลซึ่งคุณสามารถทิ้งไว้ได้ซึ่งเป็นสิ่งที่รุ่นแก้ไขของคำตอบนี้แสดงให้เห็นก่อนที่คุณจะย้อนกลับ ทำไมคุณถึงยืนยันที่จะเผยแพร่ข้อมูลที่ไม่ดีที่ฉันไม่รู้ แต่มันก็เป็นคำตอบที่ไม่ดี
mikeserv

@ mikeserv อย่างที่ฉันพูดไปแล้วขอบคุณที่ชี้ให้เห็น ฉันขอขอบคุณที่คุณช่วยฉันพัฒนาsedทักษะของฉัน ฉันยังใหม่กับsedและยังไม่สะดวกใจที่จะหลงทางจากไวยากรณ์ที่ จำกัด ที่ฉันเลือกมาจนถึงตอนนี้ นั่นsed(หึ) ฉันคิดว่าฉันคำตอบแก้ปัญหาของ OP ถึงแม้ว่ามันจะไม่ดีที่สุด (เช่นคุณ) คำตอบ นี่คือการแลกเปลี่ยนแบบสแต็กไม่ใช่วิกิพีเดียดังนั้นแก้ไขให้ถูกต้องหากฉันผิด แต่ถ้าคุณรู้คำตอบที่ดีกว่าคุณควรโพสต์ไว้เพื่อให้ผู้คนเห็นความหลากหลายของวิธีการและเปรียบเทียบพวกเขา โปรดอย่าแปลงคำตอบของฉันเป็นคำตอบของคุณด้วยฟังก์ชั่นแก้ไข
user1717828

4
มันไม่ใช่คำตอบของฉัน มันเป็นคำตอบของคุณแก้ไข นั่นคือทั้งหมดที่ และมันก็เป็นสิ่งที่ดี มันไม่ใช่อีกแล้ว
mikeserv

4

วิธีใช้งานคอลัมน์มีcutดังนี้:

echo 'abcd:bcde:cdeaf' | cut -d: -f2-

กันเลย

echo 'abcd:bcde:cdeaf' | cut -d: -f1 --complement

และรุ่นอื่น ๆ ด้วยsed(รวดเร็วยิ่งขึ้นสำหรับข้อมูลขนาดใหญ่):

echo 'abcd:bcde:cdeaf' | sed 's/^://;t;s/:/\n:/;D'

และค่อนข้างแปลกใหม่ค่ะ bash

echo 'abcd:bcde:cdeaf' | { IFS=: read -r first last ; echo "$last" ; }

หรือ

echo 'abcd:bcde:cdeaf' | { read -r line ; echo ${line#*:} ; }

หรือ

echo 'abcd:bcde:cdeaf' | { IFS=: read -a a ; printf '%b:' "${a[@]:1}\c" ; echo ;}

คุณสามารถเพิ่มวิธีการที่เหมาะสมในการทำสิ่งนั้นด้วย sed นั่นคือsed 's/[^:]*://'
don_crissti

@don_crissti รุ่นนี้มีการระบุไว้ในคำตอบข้างต้น นอกจากนี้เนื่องจากการใช้regexpมันช้ากว่าที่จะต้องรวบรวมการแสดงออกในแต่ละบรรทัด
Costas

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