使用 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

相关内容