如何使用SED在3个连续模式后插入关键字

如何使用SED在3个连续模式后插入关键字,sed,Sed,下面的示例给出了所需的结果,但它适用于连续和非连续模式搜索 我只需要对连续的模式使用这个逻辑 每连续出现3次苹果后,应插入橙色 sed "/APPLE/{p;s/.*/1/;H;g;/^\(\n1\)\{3\}$/s//ORANGES/p;d}" < input.txt > output.txt 电流输出 APPLE APPLE APPLE ORANGE APPLE APPLE APPLE ORANGE APPLE APPLE MANGO APPLE ORANG

下面的示例给出了所需的结果,但它适用于连续和非连续模式搜索

我只需要对连续的模式使用这个逻辑

每连续出现3次苹果后,应插入橙色

sed "/APPLE/{p;s/.*/1/;H;g;/^\(\n1\)\{3\}$/s//ORANGES/p;d}" < input.txt > output.txt
电流输出

APPLE
APPLE
APPLE
ORANGE
APPLE
APPLE
APPLE
ORANGE
APPLE
APPLE
MANGO
APPLE
ORANGE -------->>> NOT NEEDED <<
APPLE
苹果公司 苹果 苹果 橙色 苹果 苹果 苹果 橙色 苹果 苹果 芒果 苹果 橙色---------------->>>不需要 每连续出现3次苹果后,应插入橙色

sed "/APPLE/{p;s/.*/1/;H;g;/^\(\n1\)\{3\}$/s//ORANGES/p;d}" < input.txt > output.txt
以下脚本:

#!/bin/bash

cat <<EOF |
APPLE
APPLE
APPLE
APPLE
APPLE
APPLE
APPLE
APPLE
MANGO
APPLE
APPLE
APPLE
EOF
sed '
# Add to hold space and inspect hold space
H
x
/^\(\nAPPLE\)\{3\}$/{
    # 3 apples in hold space, means we add orange to pattern space
    # and clear hold space
    s///
    x
    s/$/\nORANGE/
    x   
}
# There are at least 3 lines in hold space
/^\(\n[^\n]*\)\{3\}/{
    # Remove first line from hold space
    s/\n[^\n]*//
}
x
'
这可能适用于您(GNU-sed):

这将在连续的3行之后附加一行
ORANGE
,其中包含字符串
APPLE

要为n条连续线(例如5条)参数化上述解决方案,请使用:

另一种选择:

sed '/APPLE/!b;:a;N;/\n[^\n]*APPLE[^\n]*$/!b;s/[^\n]*/&/3;Ta;a\ORANGE' file
如果要追加的值是变量,请使用:

sed '/APPLE/!b;:a;N;/\n[^\n]*APPLE[^\n]*$/!b;s/[^\n]*/&/3;Ta;a\'"$var" file

欢迎来到SO,感谢您展示您的努力,请在您的问题中添加输入和预期输出的示例,以使其更清楚,谢谢。它必须是
sed
?为什么不使用另一种更简单的工具呢?如果是,为什么不是python、perl或ruby?
/^\(\n1\){3\}$
为什么要检查是否有3个呢?@KamilCuk,谢谢你的回答,这里的要求仅限于与shell脚本一起使用,而不是perl或ruby。是否可以编辑/修改以下脚本以满足使用shell脚本的sed“/APPLE/{p;s/*/1/;H;g;/^(\n1)\{3\}$/s//ORANGES/p;d}”output.txt
,但sed不是shell脚本。Sed是一个外部程序,比如perl和ruby。感谢您在@potong给出的答案,如果您能向我解释这个脚本的工作原理,特别是{2..5}的用途,我将不胜感激used@Ankur第一个解决方案是连续3行,硬编码此
n;/!b
在溶液中填充两次图案。第二种解决方案是,使用
$(…)
的插值将此硬代码编程到sed程序中,同时在其中运行代码并将其替换到sed程序中
printf
将打印
n;//!b如果有四个参数,则执行四次
{2..5}
转换为
2 3 4 5
%.0s
模板接受这些参数(零宽度)。因此,代码
printf'n;//!b、 %。0s'{2..5}
转换为
n;//!Bn、 //!Bn、 //!Bn、 //!b。谢谢@potong的解释,你的备选脚本按照我需要的方式工作。但是还有一件小事情仍然没有完成,我不知道为什么会发生这种情况。。。在实际场景中,我试图通过下面的变量===pattern=orange sed'/APPLE/访问模式值(在本例中为橙色)!b、 :A.N/\n[^\n]*苹果[^\n]*$/!Bs/[^\n]*/&/3;助教;a\${pattern}'==但尽管打印橙色,它还是在output@Ankursed程序用单引号括起来,这不会插入shell变量。要允许这样做,只需用单引号括起来变量即可。但是,由于变量是程序的最后一部分,所以只需删除最后一个单引号并将其插入变量之前。请参见编辑。
sed '/APPLE/!b;'$(printf 'n;//!b;%.0s' {2..5})'a\ORANGE' file
sed '/APPLE/!b;:a;N;/\n[^\n]*APPLE[^\n]*$/!b;s/[^\n]*/&/3;Ta;a\ORANGE' file
sed '/APPLE/!b;:a;N;/\n[^\n]*APPLE[^\n]*$/!b;s/[^\n]*/&/3;Ta;a\'"$var" file