如何仅使用 sed 替换第 n 次出现的模式

如何仅使用 sed 替换第 n 次出现的模式

我搜索了整个网络,但找不到任何好的解决方案。我在许多论坛上看到这sed不是解决awk此问题的工具(但确实如此),但我不知道为什么。我的意思是您可以对出现次数 5 进行简单的替换,例如:sed 's/pattern/replace/5'仅替换第 5 个实例。为什么不能对一行sed执行's/pattern/replace/<every 5th occur>'此操作?这不是基本功能吗?

无论如何,我的问题是,我们客户的软件在 Windows 环境中运行,而 Linux 功能有限,不幸的是,awk该系统无法使用。无论出于何种原因,安装新命令对公司来说都不是一个选择。

所以我的问题是,使用sed和/或与 bash 混合使用来替换每行中第 n 次出现的模式的最佳方法是什么?无论如何我只有一行,因为我已经删除了所有换行符。bashfor循环是唯一的方法吗?

答案1

这不是一个基本功能吗?

显然不是。但它仍然是可能的

sed 's/a\([^a]*\($\|a[^a]*\($\|a[^a]*\($\|a[^a]*\($\|a\)\)\)\)\)/A\1/g'

-r我们可以删除反斜杠,这样可读性更强:

sed -r 's/a([^a]*($|a[^a]*($|a[^a]*($|a[^a]*($|a)))))/A\1/g' 

a,后跟任意数量的非a,后跟行的任一端,或者另一个a,后跟任意数量的非a,等等。第一个之后的所有内容a都会被记住\1

顺便说一句,如果 Perl 可用,您可以使用:

perl -pe 'BEGIN { @A = qw(a A) } s/a/$A[not $i++ % 5]/g'

%是模运算符。$i 随着每次匹配而递增,模的否定是 1、0、0、0、0、1 等,用作 @A 的索引来选择正确的aA

答案2

简单sed且带有括号的扩展:

sed '-es/pattern/replace/'{max..min..step} infile

代替最大限度数量 >= 出现次数图案,如果您不知道,请将其设置为文件中最长行中的最大字符数。


$ sed '-es/a/A/'{20..1..5} <<<"aaaa aaaa   a a a aa a a a aa aa"
aaaa Aaaa   a A a aa a A a aa aA

要替换第一次出现的情况,请使用以下命令:

$ sed '-es/a/A/'{{20..1..5},1} <<<"aaaa aaaa   a a a aa a a a aa aa"
Aaaa Aaaa   a A a aa a A a aa aA

相关内容