วิธีการ sed เฉพาะบรรทัดที่มีสตริงที่กำหนด?


13

INPUT:

Select ASDF 325 sdfg sdflk lk
Select TRG 46sdg rasdftz fsgs 45
Select ASDF 6ffg sdfg 4456 sdrg

เอาท์พุท:

Select ASDF 325 XXXX sdflk lk
Select TRG 46sdg rasdftz fsgs 45
Select ASDF 6ffg XXXX 4456 sdrg

ดังนั้นในระยะสั้นฉันต้อง "sed" "sdfg" ถึง "XXXX"

แต่: เฉพาะในบรรทัดที่มีสตริง "Select ASDF" .. ฉันจะทำสิ่งนี้ได้อย่างไร (sed, awk, ฯลฯ : \)

คำตอบ:


19

คุณสามารถนำหน้าคำสั่ง sed ส่วนใหญ่ด้วยที่อยู่เพื่อ จำกัด บรรทัดที่ใช้ ที่อยู่อาจจะเป็นหมายเลขบรรทัดหรือ regex /คั่นโดย

cat INPUT | sed '/Select ASDF/ s=sdfg=XXXX='

ดังที่ได้กล่าว Peter.O คำสั่งตามที่เขียนไว้ข้างต้นจะทดแทนเกิดขึ้นครั้งแรกของใด ๆในสตริงที่มีsdfg Select ASDFหากคุณต้องการแทนที่การแข่งขันที่แน่นอนเป็นsdfgเฉพาะในกรณีที่อยู่ในคอลัมน์ที่สี่คุณควรไปทางนี้:

cat INPUT | sed 's/\(^Select ASDF [^ ]* \)sdfg /\1XXXX /'

1
แล้วฟิลด์อื่นที่มีsdfg อยู่ล่ะ เช่น. 5sdfga
Peter.O

อืมจริงๆแล้วนั่นไม่ใช่ปัญหาเช่นกัน ฉันอัพเดตคำตอบแล้ว
เร่ง

มีตัวเลือกใดบ้างสำหรับการใช้: sed '/ Select ASDF / gs = sdfg = XXXX =' - ดังนั้นฉันต้องแทนที่การเกิดขึ้นทั้งหมดในบรรทัดไม่ใช่แค่ตัวแรก แต่ sed ให้ข้อผิดพลาดถ้าฉันใช้ "g"
LanceBaynes

1
คุณต้องพิมพ์gหลังจากล่าสุด=(เมื่อสิ้นสุดsคำสั่ง) มันจะเป็นเช่นนี้:sed '/Select ASDF/ s=sdfg=XXXX=g'
เร่ง

7

หากคุณเพียงแค่เปลี่ยนคอลัมน์ 4 หากมีค่าที่แน่นอนให้ใช้ตัวดำเนินการความเสมอภาคแทนนิพจน์ทั่วไปที่สมเหตุสมผล

awk '$1 == "Select" && $2 == "ASDF" && $4 == "sdfg" {$4 = "XXXX"} {print}'

1
ด่วน! .. เปรียบเทียบกับ 1 ล้านบรรทัดกับ Birei awk และ Rush ของsed ตำแหน่ง : 0m1.580s เทียบกับ0m3.792sเทียบกับ0m6.740s
Peter.O

1

การใช้GNU awk:

awk '
    BEGIN { IGNORECASE = 1 } 
    /^select asdf/ { 
        sub( /\<sdfg\>/, "XXXX", $0 ) 
    } 
    { print }
' infile

เอาท์พุท:

Select ASDF 325 XXXX sdflk lk
Select TRG 46sdg rasdftz fsgs 45
Select ASDF 6ffg XXXX 4456 sdrg

UPDATE : หลีกเลี่ยงIGNORECASEการไม่ใช่ GNU awkและตรงตามตัวพิมพ์ใหญ่ - เล็ก ขอบคุณjw013ที่ชี้รายละเอียดดังกล่าว:

awk ' 
    /^Select ASDF/ { 
        sub( /\<sdfg\>/, "XXXX", $0 ) 
    } 
    { print }
' infile

1
คุณควรพูดถึงIGNORECASEคือ GNU awk/ gawkส่วนขยาย
jw013

1
@ jw013: ขอบคุณ อัปเดตคำตอบพร้อมคำแนะนำของคุณ
Birei

4
IGNORECASE ไม่ถูกต้องในกรณีนี้ไม่ว่าจะเป็น GNU หรือ G'not .. เกณฑ์ของคำถามนั้นชัดเจนสำหรับตัวพิมพ์ใหญ่ASDF
Peter.O
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.