Làm thế nào để sed chỉ các dòng có chứa chuỗi đã cho?


13

ĐẦU VÀO:

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

ĐẦU RA:

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

Vì vậy, trong ngắn hạn, tôi cần "sed" "sdfg" thành "XXXX".

NHƯNG: chỉ trong các dòng có chứa chuỗi "Chọn ASDF" .. Làm thế nào tôi có thể làm điều này? (sed, awk, v.v .: \)

Câu trả lời:


19

Bạn có thể tiền tố hầu hết các lệnh sed với một địa chỉ để giới hạn các dòng mà chúng áp dụng. Một địa chỉ có thể là số dòng hoặc regex được phân định bởi /.

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

Như Peter.O đã đề cập, lệnh như được viết ở trên sẽ thay thế lần xuất hiện đầu tiên của bất kỳ sdfgchuỗi nào có chứa Select ASDF. Nếu bạn cần thay thế khớp chính xác thành sdfgchỉ trong trường hợp nó ở cột thứ tư, bạn nên đi theo cách này:

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

1
Còn một lĩnh vực khác có chứa sdfg thì sao? ví dụ. 5sdfga
Peter.O

Hmm, thực sự đó không phải là vấn đề. Tôi đã cập nhật câu trả lời của mình.
vội vàng

Có bất kỳ tùy chọn nào để sử dụng: sed '/ Chọn ASDF / gs = sdfg = XXXX =' - vì vậy tôi cần thay thế tất cả các lần xuất hiện trong một dòng, không chỉ lần đầu tiên. nhưng sed sẽ báo lỗi nếu tôi sử dụng "g"
LanceBaynes

1
Bạn cần gõ gsau cùng =(ở cuối slệnh). Nó sẽ như thế này:sed '/Select ASDF/ s=sdfg=XXXX=g'
vội vàng

7

Nếu bạn chỉ thay đổi cột 4 nếu nó có giá trị chính xác, thì sử dụng các toán tử đẳng thức thay vì các biểu thức thông thường có ý nghĩa.

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

1
Nhanh! .. so sánh nó, với 1 triệu dòng, với awk của Birei và sed vị trí của Rush : 0m1.580s so với 0m3.792s so với 0m6.740s
Peter.O

1

Sử dụng GNU awk:

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

Đầu ra:

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

CẬP NHẬT : Tránh IGNORECASEcho không phải là GNU awkvà phù hợp với trường hợp nhạy cảm. Cảm ơn jw013 , người đã chỉ ra chi tiết đó:

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

1
Bạn nên đề cập đến IGNORECASElà một GNU awk/ gawkphần mở rộng.
jw013

1
@ jw013: Cảm ơn bạn. Cập nhật câu trả lời với đề nghị của bạn.
Birei

4
IGNORECASE sai trong trường hợp này, cho dù đó là GNU hay G'not .. Tiêu chí trong câu hỏi rõ ràng là dành cho chữ hoaASDF
Peter.O
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.