我知道如何使用sed
with[^xxxx]
语法来排除字符,但是如何排除一个词呢?例如我的变量:
var="
Now is the time
for all good men
to come
to the aid
of the party"
现在:
echo $var | sed ...
...我想结束:
REPLACED time
for all good men
to come
REPLACED aid
REPLACED party
...这应该很简单,但我不知道该怎么做。
echo $var | sed -r 's/^[^the]*the/REPLACED/'
...有点接近,但t
h
e
匹配为单个字符,而不是单词the
。
如果有解决方案,我可以将所有内容替换为多次出现的第一个,甚至可以替换为特定的出现,那会更好。
您可以按如下方式实现,假设
the
线上最多有一个实例:the
这将用您的替换文本替换直到最后一次出现的所有内容(请记住,正则表达式是贪婪的) 。the
用非单词字符括起来(以防止部分单词匹配,例如),包括在捕获组中以 ,theoretical
结尾的非单词字符。the
( ... )
\1
因为它是搜索模式中的第一个这样的组)。这种有点复杂的方法是必要的,以便终止的字符the
也被转移到替换文本中。如果您想替换第一次出现的所有内容,您可能不得不求助于
awk
:这将检查
the
被非单词字符包围的字符串是否出现在行中,并将位置存储在变量i
中。i
非零,它将在出现之后打印替换文本和当前输入行的子字符串the
,否则跳过执行到下一行。i
为零,它只是按原样打印当前行。s/.*the/REPLACED/
替换直到最右边出现的所有内容,the
因为它.*
很贪婪并且希望尽可能多地匹配。.*
是 0 个或多个 (*
) 个字符 (.
)尽可能多,并且会愉快地吞噬所有出现的the
不包括最后一个需要与正the
则表达式的以下部分匹配的字符。大约 30 年前,
perl
5 引入了*
:的变体*?
,它也匹配 0 个或多个前面的事物,但尽可能少:很少有人
sed
添加了对这些新perl
运算符的支持。我只知道两种实现方式(ssed
with-R
和 ast-open 的 with-E
/-A
/-X
/-P
)。在其他sed
s 中,?
与文字匹配?
或与-E
/匹配-r
,*?
要么是错误,要么与*
理解为*
运算符(0 或更多)与?
(0 或 1)组合相同。对于
sed
不支持的实现*?
,当要替换的是单个字符(如x
)时,您s/[^x]*x/REPLACE/
可以说 0 或更多(*
)字符而不是x
([^x]
),尽可能多,并且因为我们排除x
了 ,它将存储在第一个之前x
发生。你不能将它用于超过一个字符的字符串,因为你不能尽可能多地说 0 个或多个字符,只要不包括 "the"。所以你需要一种不同的方法。
s/the/REPLACEMENT/
替换第一次出现的the
,因此标准sed
中替换所有字符直到第一次出现的字符串的常用方法是用换行符替换它(否则保证该字符不会出现在模式空间中),然后替换该换行符之前的所有内容:如果您需要将所有内容替换为第一个
the
,您可能需要非贪婪量词,而基本正则表达式和扩展正则表达式都无法识别这些量词。在那种情况下,如果
sed
对你来说不是强制性的,你可以使用perl
:如果您需要替换最多
n
出现次数(替换n
为您的出现次数):