Bagaimana sed sed hanya garis yang berisi string yang diberikan?

13

MEMASUKKAN:

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

KELUARAN:

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

Jadi singkatnya saya perlu "sed" "sdfg" ke "XXXX".

TETAPI: hanya di baris yang berisi string "Pilih ASDF" .. Bagaimana saya bisa melakukan ini? (sed, awk, dll.: \)

LanceBaynes
sumber

Jawaban:

19

Anda dapat mengawali sebagian besar perintah sed dengan alamat untuk membatasi baris yang mereka terapkan. Alamat dapat berupa nomor baris, atau regex yang dibatasi oleh /.

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

Seperti disebutkan Peter.O, perintah seperti yang ditulis di atas akan menggantikan kemunculan pertama dari setiap sdfgyang berisi string Select ASDF. Jika Anda perlu mengganti kecocokan persis dengan sdfghanya dalam kasus ini di kolom keempat Anda harus begini:

cat INPUT | sed 's/\(^Select ASDF [^ ]* \)sdfg /\1XXXX /'
buru-buru
sumber
1
Bagaimana dengan bidang lain yang mengandung sdfg ? misalnya. 5sdfga
Peter.O
Hmm, sebenarnya bukan itu masalahnya juga. Saya telah memperbarui jawaban saya.
buru
apakah ada opsi untuk menggunakan: sed '/ Select ASDF / gs = sdfg = XXXX =' - jadi saya perlu mengganti semua kejadian dalam satu baris, bukan hanya yang pertama. tapi sed memberikan kesalahan jika saya menggunakan "g"
LanceBaynes
1
Anda harus mengetik gsetelah terakhir =(di akhir sperintah). Akan seperti ini:sed '/Select ASDF/ s=sdfg=XXXX=g'
buru
7

Jika Anda hanya mengubah kolom 4 jika memiliki nilai yang tepat, maka menggunakan operator kesetaraan bukan ekspresi reguler masuk akal.

awk '$1 == "Select" && $2 == "ASDF" && $4 == "sdfg" {$4 = "XXXX"} {print}'
glenn jackman
sumber
1
Cepat! .. membandingkannya, untuk 1 juta baris, dengan awak Birei dan sed posisi Rush : 0m1.580s vs. 0m3.792s vs 0m6.740s
Peter.O
1

Menggunakan GNU awk:

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

Keluaran:

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

UPDATE : Hindari IGNORECASEuntuk non-GNU awk, dan cocok dengan huruf besar-kecil. Terima kasih kepada jw013 , yang menunjukkan detail itu:

awk ' 
    /^Select ASDF/ { 
        sub( /\<sdfg\>/, "XXXX", $0 ) 
    } 
    { print }
' infile
Birei
sumber
1
Yang harus Anda sebutkan IGNORECASEadalah GNU awk/ gawkekstensi.
jw013
1
@ jw013: Terima kasih. Jawaban diperbarui dengan saran Anda.
Birei
4
IGNORECASE salah dalam kasus ini, apakah itu GNU atau G'not .. Kriteria dalam pertanyaan ini secara eksplisit untuk huruf besarASDF
Peter.O