
我需要在包含電子郵件地址的文件中將_
(底線)替換為(問號)。?
該文件如下所示:
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