根据多个匹配项将行添加到文本文件

Add line to text file based on multiple matches

我正在尝试使用 sed、awk 或其他 Linux 标准命令修改文件,以便在匹配以某些公共字符开头的两行时,插入一行显示该部分的文本已结束。

给出的内容如下:

a 2021-08-12 14:42:21.0
b 2021-08-12 14:42:22.0
a 2021-08-12 14:42:22.0
b 2021-08-12 14:42:22.0
b 2021-08-12 14:42:23.0
c 2021-08-12 14:42:54.0
c 2021-08-12 14:42:54.0
a 2021-08-12 14:43:27.0
b 2021-08-12 14:43:27.0
a 2021-08-12 14:43:28.0
b 2021-08-12 14:43:28.0
b 2021-08-12 14:43:28.0
c 2021-08-12 14:43:59.0
c 2021-08-12 14:44:00.0
a 2021-08-12 14:44:33.0
b 2021-08-12 14:44:33.0
c 2021-08-12 14:45:06.0
a 2021-08-12 14:45:39.0
b 2021-08-12 14:45:39.0
a 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
c 2021-08-12 14:46:11.0
c 2021-08-12 14:46:11.0

我想结束:

a 2021-08-12 14:45:39.0
b 2021-08-12 14:45:39.0
a 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
c 2021-08-12 14:46:11.0
c 2021-08-12 14:46:11.0
##Some Text##
a 2021-08-12 14:45:39.0
b 2021-08-12 14:45:39.0
a 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
c 2021-08-12 14:46:11.0
c 2021-08-12 14:46:11.0
##Some Text##
a 2021-08-12 14:44:33.0
b 2021-08-12 14:44:33.0
c 2021-08-12 14:45:06.0*
a 2021-08-12 14:45:39.0
b 2021-08-12 14:45:39.0
a 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
c 2021-08-12 14:46:11.0
c 2021-08-12 14:46:11.0
##Some Text##

你可能会看到,在最后一个序列之前,有一个失败的测试没有成功完成......如果这个也能处理,那就太好了,一个结束在新数据集以 'a' 开始之前,数据集将始终为 'c',如果不容易,请不要担心,这并不经常需要担心。在这种情况下,程序每次迭代输出 7 行,但可以有任意数量的步骤。

我试过类似的东西:

sed '/3 /{p;s/.*/1/;H;g;/^\(\n1\)\{2\}$/s//##TEXT##/p;d}'
sed -z 's/^3/&\n##TEXT##/2'
sed  -e '/^\[3 \]$/,/^\[2 \]/{/^1 .*/a'"##TEXT##" -e '}'

我似乎无法让它工作....找到 2 行以相同模式或字符开头的位置,在匹配后插入一些文本。

感谢任何帮助!!

谢谢 /G

这就是您要求的(在以 c 开头的 2 行背对背打印文本后):

$ awk '{print} (=="c") && (p==){ print "##Some Text##" } {p=}' file
a 2021-08-12 14:42:21.0
b 2021-08-12 14:42:22.0
a 2021-08-12 14:42:22.0
b 2021-08-12 14:42:22.0
b 2021-08-12 14:42:23.0
c 2021-08-12 14:42:54.0
c 2021-08-12 14:42:54.0
##Some Text##
a 2021-08-12 14:43:27.0
b 2021-08-12 14:43:27.0
a 2021-08-12 14:43:28.0
b 2021-08-12 14:43:28.0
b 2021-08-12 14:43:28.0
c 2021-08-12 14:43:59.0
c 2021-08-12 14:44:00.0
##Some Text##
a 2021-08-12 14:44:33.0
b 2021-08-12 14:44:33.0
c 2021-08-12 14:45:06.0
a 2021-08-12 14:45:39.0
b 2021-08-12 14:45:39.0
a 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
c 2021-08-12 14:46:11.0
c 2021-08-12 14:46:11.0
##Some Text##

但我认为这可能是您实际需要的(在不以 c 开头的行之前打印文本,而在它之前的行确实以 c 开头),假设输入 c 2021-08-12 14:45:06.0* 中的行是您在“有一个失败的测试尚未成功完成……如果这也可以处理”中提到的情况,以及您想要的方式handled 是打印与我们打印该文本的其他情况相同的文本:

$ awk 'BEGIN{txt="##Some Text##"} (!=p) && (p=="c"){ print txt } {print; p=} END{ print txt }' file
a 2021-08-12 14:42:21.0
b 2021-08-12 14:42:22.0
a 2021-08-12 14:42:22.0
b 2021-08-12 14:42:22.0
b 2021-08-12 14:42:23.0
c 2021-08-12 14:42:54.0
c 2021-08-12 14:42:54.0
##Some Text##
a 2021-08-12 14:43:27.0
b 2021-08-12 14:43:27.0
a 2021-08-12 14:43:28.0
b 2021-08-12 14:43:28.0
b 2021-08-12 14:43:28.0
c 2021-08-12 14:43:59.0
c 2021-08-12 14:44:00.0
##Some Text##
a 2021-08-12 14:44:33.0
b 2021-08-12 14:44:33.0
c 2021-08-12 14:45:06.0
##Some Text##
a 2021-08-12 14:45:39.0
b 2021-08-12 14:45:39.0
a 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
c 2021-08-12 14:46:11.0
c 2021-08-12 14:46:11.0
##Some Text##

或者如果您想要在以单个 c 而不是 2 c 结束的块的情况下打印不同的文本:

$ awk '
    (!=p) && (p=="c"){ prt() } {print; pp=p; p=} END{ prt() }
    function prt() { print (pp==p ? "##Some Text##" : "##Some Other Text##") }
' file
a 2021-08-12 14:42:21.0
b 2021-08-12 14:42:22.0
a 2021-08-12 14:42:22.0
b 2021-08-12 14:42:22.0
b 2021-08-12 14:42:23.0
c 2021-08-12 14:42:54.0
c 2021-08-12 14:42:54.0
##Some Text##
a 2021-08-12 14:43:27.0
b 2021-08-12 14:43:27.0
a 2021-08-12 14:43:28.0
b 2021-08-12 14:43:28.0
b 2021-08-12 14:43:28.0
c 2021-08-12 14:43:59.0
c 2021-08-12 14:44:00.0
##Some Text##
a 2021-08-12 14:44:33.0
b 2021-08-12 14:44:33.0
c 2021-08-12 14:45:06.0
##Some Other Text##
a 2021-08-12 14:45:39.0
b 2021-08-12 14:45:39.0
a 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
b 2021-08-12 14:45:40.0
c 2021-08-12 14:46:11.0
c 2021-08-12 14:46:11.0
##Some Text##

上面的 p 只是一个变量,它保存了 $1 的前一个值,而 pp 保存了 2 行后面的 $1 的值。

以下测试使用 GNU sed 4.8 和 BSD sed 版本 (2005) 由 Apple 在 macOS 上发布。

正如您从 sed 开始的那样,这里有一个 sed 解决方案。我假设您想在以 c 开头的连续两行之后插入您的文本(不确定我是否完全理解您的规格):

sed -E '/^c/{x;/^c/a\
##Some Text##
;x;};h' data.txt

最后的 h 复制保留 space 中的每一行。当一行以 c 开头(匹配 /^c/)时,我们交换模式 space 和保留 space,如果后者也以 c 开头,我们附加文本;当然我们交换回模式 space 和保持 space.

如果您更喜欢单行命令并且您的 shell 是 bash:

sed -E $'/^c/{x;/^c/a\\n##Some Text##\n;x;};h' data.txt