วิธีที่ดี
โดยปกติคุณไม่สามารถใช้ grep ได้ แต่คุณสามารถใช้เครื่องมืออื่น ๆ ได้ AWK ถูกกล่าวถึงแล้ว แต่คุณสามารถใช้sed
เช่นนี้:
sed -e '1p' -e '/youpattern/!d'
มันทำงานอย่างไร:
ยูทิลิตี้ Sed ทำงานบนแต่ละบรรทัดแยกกันโดยรันคำสั่งที่ระบุในแต่ละบรรทัด คุณสามารถมีหลายคำสั่งโดยระบุหลาย-e
ตัวเลือก เราสามารถผนวกแต่ละคำสั่งด้วยพารามิเตอร์ช่วงที่ระบุว่าควรใช้คำสั่งนี้กับบรรทัดที่ระบุหรือไม่
"1p" เป็นคำสั่งแรก มันใช้p
คำสั่งซึ่งปกติจะพิมพ์ทุกบรรทัด แต่เราเติมมันด้วยค่าตัวเลขที่ระบุช่วงที่ควรนำไปใช้ ที่นี่เราใช้1
ซึ่งหมายถึงบรรทัดแรก หากคุณต้องการพิมพ์บรรทัดเพิ่มเติมคุณสามารถใช้x,yp
ตำแหน่งที่x
จะพิมพ์บรรทัดแรกเป็นบรรทัดy
สุดท้ายในการพิมพ์ ตัวอย่างเช่นการพิมพ์ 3 บรรทัดแรกคุณจะใช้1,3p
คำสั่งถัดไปd
ซึ่งโดยปกติจะลบบรรทัดทั้งหมดจากบัฟเฟอร์ ก่อนหน้าคำสั่งนี้เราใส่yourpattern
ระหว่างสอง/
ตัวละคร นี่คือวิธีอื่น (ก่อนอื่นคือระบุบรรทัดที่เราทำด้วยp
คำสั่ง) ของการกำหนดแอดเดรสบรรทัดที่คำสั่งควรรันอยู่ ซึ่งหมายความว่าคำสั่งจะใช้งานได้กับบรรทัดที่ตรงกันyourpattern
เท่านั้น ยกเว้นว่าเราจะใช้!
ตัวอักษรก่อนd
คำสั่งซึ่งกลับเหตุผลของมัน ดังนั้นตอนนี้มันจะลบบรรทัดทั้งหมดที่ไม่ตรงกับรูปแบบที่ระบุ
ในตอนท้าย sed จะพิมพ์บรรทัดทั้งหมดที่เหลืออยู่ในบัฟเฟอร์ แต่เราลบบรรทัดที่ไม่ตรงจากบัฟเฟอร์ดังนั้นเฉพาะบรรทัดที่ตรงกันเท่านั้นที่จะถูกพิมพ์
เพื่อสรุป: เราพิมพ์บรรทัดที่ 1 จากนั้นเราจะลบบรรทัดทั้งหมดที่ไม่ตรงกับรูปแบบของเราออกจากอินพุต ส่วนที่เหลือของสายจะถูกพิมพ์ (เส้นเท่านั้นดังนั้นที่ทำตรงกับรูปแบบ)
ปัญหาบรรทัดแรก
ดังกล่าวในความคิดเห็นมีปัญหากับวิธีนี้ หากรูปแบบที่ระบุตรงกับบรรทัดแรกก็จะถูกพิมพ์สองครั้ง (ครั้งเดียวโดยp
คำสั่งและอีกครั้งเพราะการแข่งขัน) เราสามารถหลีกเลี่ยงปัญหานี้ได้สองวิธี:
การเพิ่มคำสั่งหลัง1d
1p
ดังที่ฉันได้กล่าวไปแล้วd
คำสั่งจะลบบรรทัดออกจากบัฟเฟอร์และเราระบุช่วงเป็นหมายเลข 1 ซึ่งหมายความว่ามันจะลบบรรทัดที่ 1 เท่านั้น ดังนั้นคำสั่งจะเป็นsed -e '1p' -e '1d' -e '/youpattern/!d'
การใช้คำสั่งแทน1b
1p
มันเป็นเคล็ดลับ b
คำสั่งอนุญาตให้เราข้ามไปยังคำสั่งอื่นที่ระบุโดยเลเบล แต่ถ้าไม่ได้ระบุป้ายกำกับนี้ (ตามตัวอย่างของเรา) เพียงแค่ข้ามไปยังจุดสิ้นสุดของคำสั่งให้ละเว้นคำสั่งที่เหลือสำหรับบรรทัดของเรา ดังนั้นในกรณีของเราd
คำสั่งสุดท้ายจะไม่ลบบรรทัดนี้ออกจากบัฟเฟอร์
ตัวอย่างเต็มรูปแบบ:
ps aux | sed -e '1b' -e '/syslog/!d'
ใช้เครื่องหมายอัฒภาค
sed
การใช้งานบางอย่างสามารถช่วยคุณประหยัดการพิมพ์โดยใช้อัฒภาคเพื่อแยกคำสั่งแทนที่จะใช้หลาย-e
ตัวเลือก ดังนั้นหากคุณไม่สนใจที่จะพกพาคำสั่งจะเป็นps aux | sed '1b;/syslog/!d'
เช่นนั้น มันทำงานอย่างน้อยในGNU sed
และbusybox
การใช้งาน
ทางบ้า
อย่างไรก็ตามนี่เป็นวิธีที่ค่อนข้างบ้าในการทำเช่นนี้กับ grep มันไม่เหมาะสมแน่นอนฉันโพสต์สิ่งนี้เพื่อการเรียนรู้เท่านั้น แต่คุณสามารถใช้มันได้เช่นถ้าคุณไม่มีเครื่องมืออื่นในระบบของคุณ:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog'
มันทำงานอย่างไร
ก่อนอื่นเราใช้-n
ตัวเลือกเพื่อเพิ่มหมายเลขบรรทัดก่อนแต่ละบรรทัด เราต้องการที่จะนับจำนวนบรรทัดทั้งหมดที่เราจับคู่ไว้.*
- อะไรก็ได้แม้แต่บรรทัดที่ว่างเปล่า ตามที่แนะนำในความคิดเห็นเราสามารถจับคู่ '^' ผลลัพธ์เหมือนกัน
จากนั้นเราใช้นิพจน์ทั่วไปเพิ่มเติมเพื่อให้เราสามารถใช้\|
อักขระพิเศษซึ่งทำงานเป็น OR ดังนั้นเราจะจับคู่ว่าบรรทัดเริ่มต้นด้วย1:
(บรรทัดแรก) หรือมีรูปแบบของเรา (ในกรณีนี้คือsyslog
)
ปัญหาหมายเลขบรรทัด
ตอนนี้ปัญหาคือเราได้รับหมายเลขบรรทัดที่น่าเกลียดนี้ในผลลัพธ์ของเรา หากนี่เป็นปัญหาเราสามารถลบออกได้cut
เช่นนี้
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog' | cut -d ':' -f2-
-d
ตัวเลือกระบุตัวคั่น-f
ระบุเขตข้อมูล (หรือคอลัมน์) ที่เราต้องการพิมพ์ ดังนั้นเราจึงต้องการตัดแต่ละบรรทัดของ:
ตัวละครทุกตัวและพิมพ์เฉพาะคอลัมน์ที่ 2 และคอลัมน์ถัดไปทั้งหมด สิ่งนี้จะลบคอลัมน์แรกอย่างมีประสิทธิภาพด้วยตัวคั่นและนี่คือสิ่งที่เราต้องการ
ack
นั้นมีประโยชน์มากและทำไมความนิยมในperl
อดีตจึงพุ่งสูงขึ้นไปsed
อีกawk
: มันเป็นสิ่งสำคัญที่ชิ้นส่วนต่างๆจะต้องรวมเข้าด้วยกัน