使用 sed 或 awk 替換第一次和第二次搜尋之間的字串中的字符

使用 sed 或 awk 替換第一次和第二次搜尋之間的字串中的字符

我需要在包含電子郵件地址的文件中將_(底線)替換為(問號)。?

該文件如下所示:

EFT_020034-E015133  20140624    /ACC/[email protected]         SHR    END 
EFT_020034-E015133  20140624    /ACC/[email protected]     SHR    END
EFT_020034-E015133  20140624    /ACC/[email protected]        SHR    END

預期輸出為:

EFT_020034-E015133  20140624    /ACC/[email protected]         SHR    END 
EFT_020034-E015133  20140624    /ACC/[email protected]     SHR    END
EFT_020034-E015133  20140624    /ACC/[email protected]        SHR    END

我怎樣才能做到這一點sed或者awkEMAIL+不影響其他底線,僅影響(constant) 和(constant)之間的底線SHR。更改的內容應保存在新文件中。

答案1

awk 會這樣做:

$ awk '{ gsub("_", "?", $3) ; print }' < data
EFT_020034-E015133 20140624 /ACC/[email protected] SHR END
EFT_020034-E015133 20140624 /ACC/[email protected] SHR END
EFT_020034-E015133 20140624 /ACC/[email protected] SHR END

電子郵件地址位於欄位 3 中,因此我們僅在欄位 3 中替換_?,包括當有多個 時_,使用gsub

答案2

sed你一起可以做:

sed -e :1 -e 's/_\([^+]*@\)/?\1/;t1'

即替換_後跟一個非字元序列+,然後@?字元序列替換,只要匹配就重複此過程。

EMAIL+或只在和之間執行此操作SHR

sed -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/\1?\2/;t1'

如果您只想考慮以 開頭的行^EFT,您可以添加 a-e '/^EFT/!b'來忽略那些不喜歡的行:

sed -e '/^EFT/!b' -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/\1?\2/;t1'

請注意,對於如下輸入:

EFT EMAIL+ foo_bar SHR bar_baz EMAIL+ SHR

兩個底線都會被替換,因為它們都在 anEMAIL+和 a之間SHR

為了避免這種情況,你可以這樣做:

sed '
  /^EFT/!b # leave the non-EFT lines alone (branch out)
  s/%/%p/g; s/</%l/g; s/>/%r/g; # escape the <>% characters with %
  s/EMAIL+/</g; s/SHR/>/g; # replace EMAIL+ and SHR with < and >
  :1
  s/\(<[^<>]*\)_\([^<>]*>\)/\1?\2/; t1
  s/</EMAIL+/g; s/>/SHR/g; # restore EMAIL+ and SHR
  s/%r/>/g; s/%l/</g; s/%p/%/g; # restore the escaped <>%'

答案3

sed '/.*EMAIL+\(.*\)SHR.*/{
    h;s//\1/;y/_/?/;G
    s/\(.*\)\n\(.*EMAIL+\).*SHR/\2\1SHR/}'

這應該非常可靠地完成這項工作 - 它將替換行上最後一個出現的行和同一行上最後一個出現的行之間的所有_內容,並且僅在包含兩個字串的行上替換所有內容。?EMAIL+SHR

相關內容