如何使用 sed 删除两个字符之间的所有文本……
例如:
[email protected]
[email protected]
[email protected]
我想将电子邮件中的文字“+”改为“@”。(连“+”也要删除,而“@”符号要保留)
我使用了以下命令:
sed -e 's/\(+\).*\(@\)/\1\2/' FILE.txt > RESULT.txt
但文件的输出中包含“+”号。例如:[电子邮件保护]
我想要以下输出:
[email protected]
[email protected]
[email protected]
有人可以帮我修改上面的 sed 命令吗?
答案1
简单的解决方案是匹配您想要保留的匹配边界,然后将它们放回原处,中间不放置任何内容。
sed 's/+[^@+]*@/@/' FILE.txt >RESULT.txt
您把不想保留的东西放回去了,这显然会产生错误的结果。
您可以使用\(
...\)
分组括号捕获要保留的字符串,但在这种情况下,由于它是一个完全静态的字符串,我选择使正则表达式和替换字符串尽可能简单,并且仅将其硬编码@
为替换字符串。
还要注意正则表达式如何注意不跨越多个加号或@
符号。也许你确实想跨越任何重复的+
字符;然后从否定字符类中取出加号,只留下[^@]
。
答案2
我将从原始命令开始,而不是从头开始构建。在这种情况下,从头开始构建是一种很好的方法,但理解原始命令以及可以采取哪些步骤来调整命令以满足您的需求仍然具有教育价值。
原始命令的核心:
sed -e 's/\(+\).*\(@\)/\1\2/'
表达式的形式为s/pattern/replacement/
,表示“搜索pattern
并替换为replacement
”。/
这里的分隔符是。
您的pattern
是\(+\).*\(@\)
。如果是 ,其匹配函数将相同+.*@
(将某些内容括在 中\( \)
与 的上下文相关replacement
,我们将讨论它)。 的模式+.*@
意味着“文字+
后跟(几乎)任何字符(.
)重复零次或多次(*
),后跟文字@
”。
注意+
匹配第一个可能的字符+
,并且*
是贪婪的,所以这个匹配从第一个+
到最后一个@
。在你的具体情况下这可能并不重要,但有时它非常重要。
您的替换是\1\2
。它的意思是“第一个匹配的内容\( \)
,后面跟着第二个匹配的内容\( \)
”。您的第一个\( \)
实际上是\(+\)
,它匹配+
您想要删除的内容。
要清楚:这些\( \)
组出现在模式中(因此模式不仅仅是+.*@
)的原因是它们定义了后来称为\1
和的片段\2
。
因此,如果您不想+
打印,对原始命令的最小更改将是省略,因为这是在您的情况下\1
打印的确切部分。+
sed -e 's/\(+\).*\(@\)/\2/'
但是你不需要在模式中,因此你可以简化\( \)
:+
sed -e 's/+.*\(@\)/\1/'
注意,因为现在是第一组,所以\2
变成了。此外,由于它只能匹配,因此您可以使用文字代替:\1
\(@\)
\( \)
@
@
\1
sed -e 's/+.*\(@\)/@/'
但现在你根本不需要\( \)
。命令变成:
sed -e 's/+.*@/@/'
然后你回想一下*
是贪婪的,所以.*
可能包括 (extra) +
or/and @
。假设你不想要这个。你需要变成匹配除or.
之外的任何内容的东西:@
+
sed -e 's/+[^@+]*@/@/'
这正是另一个答案给你。有一定经验的sed
用户会从头开始构建此解决方案。如您所见,可以逐步以合乎逻辑的方式简化原始命令,并获得相同的解决方案。