当区域重叠时,Sed 不会替换文件中的所有实例
我需要用其他单词替换几个单词。
例如:file
中的“apple”和“FRUIT”,仅在这4种情况:
_apple_
前后有空格。[apple_
,前面有一个方括号,后面有一个空格。_apple]
,前面有一个空格,后面有一个方括号。[apple]
,前后都有方括号。
我不希望在任何其他情况下发生替换。
我尝试使用以下代码:
a="apple"
b="fruit"
sed -i "s/ $a / $b /g" ./file
sed -i "s/\[$a /\[$b /g" ./file
sed -i "s/ $a\]/ $b\]/g" ./file
sed -i "s/\[$a\]/\[$b\]/g" ./file
我认为末尾的选项“g”意味着它将替换所有实例,但我发现这不是一个彻底的解决方案。例如,如果 file
包含以下内容:
apple spider apple apple spider tree apple tree
第三次出现的“apple”不会被替换。同样在此,该词的几次出现都没有改变:
apple spider apple apple apple apple apple spider tree apple tree
我怀疑这是因为共享“空间”。
我怎样才能找到并用 $b
替换 $a
的所有实例,无论是否有重叠?
I need to replace several words with other words.
For e.g.: "apple" with "FRUIT" in file
, only in these 4 situations:
_apple_
, has a blank space before and after.[apple_
, has a square opening bracket before and a blank space after._apple]
, has a blank space before and a square closing bracket after.[apple]
, has square brackets before and after.
I do not want the replaces to occur in any other situation.
I have tried using the following code:
a="apple"
b="fruit"
sed -i "s/ $a / $b /g" ./file
sed -i "s/\[$a /\[$b /g" ./file
sed -i "s/ $a\]/ $b\]/g" ./file
sed -i "s/\[$a\]/\[$b\]/g" ./file
I thought the option "g" at the end would mean it would replace all instances, but I found this is not a thorough solution. For e.g. if file
contains this:
apple spider apple apple spider tree apple tree
The third occurrence of "apple" is not being replaced. Also in this, several appearances of the word are not changed:
apple spider apple apple apple apple apple spider tree apple tree
I suspect this is because the shared "space".
How can I get this to find and replace all instances of $a
with $b
, regardless of any overlap?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
快速而肮脏的解决方案是执行两次更换。
这是安全的,因为在第一个命令之后,生成的文本将不会包含原始文本中未出现的任何
(\[| )apple( |\])
。缺点是两次替换大约需要两倍的时间来运行。
如果您在两次执行sed中中断它,您可以更清楚地看到步骤:
The quick-and-dirty solution is to perform the replacement twice.
This is safe because, after the first command, the resulting text won't contain any occurrences of
(\[| )apple( |\])
that were not already in the original text.The drawback is that two replacements take roughly twice more time to run.
If you break it in two executions of sed, you can see the steps clearer:
您可以使用反向引用来做到这一点。这应该完全兼容 POSIX
示例
You can do this using backreferences. This should be fully POSIX compatible
Example
\b
匹配单词边界。可能不完全便携,至少不能在 Mac OS X 上运行。还有一个更有趣的测试:
\b
matches word boundaries. Probably not entirely portable, doesn't work on Mac OS X at least.And a more interesting test:
考虑使用向前看和向后看:
演示: http://regexr.com?2vl8p
好的,我测试了 <现在在我的计算机中运行 code>regex 并注意到向前查找和向后查找在标准
sed
中不起作用,您可以将ssed
与--regexp-perl
选项改为:Consider using look ahead and look behinds:
Demo: http://regexr.com?2vl8p
Okay, I tested the
regex
in my computer now and noted that look aheads and look behinds doesn't work in standardsed
, you would usessed
with--regexp-perl
option instead:使用 sed 的一种方法:
共有三个替换命令。说明:
我的测试:
文件的内容:
设置变量:
运行
sed
命令:结果:
如果你的真实文件有不同的内容,它将不起作用分配空格或具有奇怪的格式。在这种情况下,
sed
是一个有限的工具,最好是perl
或具有前向和后向功能的类似工具。One way using
sed
:There are three substitution commands. Explanation:
My test:
Content of file:
Set variables:
Run
sed
command:Result:
It won't work if your real file has different distribution of spaces or has a strange format. In that case,
sed
is a limited tool, it would be betterperl
or similar with look-aheads and look-behinds.