搜索模式,然后在第三个空行中添加文本

搜索模式,然后在第三个空行中添加文本

搜索pattern,然后对pattern后面的每个空行进行计数,直到找到第3个空行;然后我想在该空行中放置一个逗号和分号。空行之间可能有大量数据,或者空行之间只有一行文本。

GROUP DIRECTORY CATEGORIES
datadata

Grouping Cat
datadata

datadata
this is the 3rd blank line

我已尝试以下操作但没有成功。有什么建议么?

sed '/GROUP DIRECTORY CATEGORIES/,/^$/^$/^$/,;/' file1>file2
sed '/GROUP DIRECTORY CATEGORIES/$/$/$/,;/' file1>file2
sed '/GROUP DIRECTORY CATEGORIES/{$;$;$/./,;/1;}' file1>file2

答案1

虽然sed可以用于此目的,但是使用 可以更轻松地完成任何涉及计数的事情awk

让我们考虑这个测试文件:

$ cat file1
GROUP DIRECTORY CATEGORIES
datadata

Grouping Cat
datadata

datadata

Above is 3rd blank line

要将 a 添加,;到之后的第三个空行GROUP DIRECTORY CATEGORIES

$ awk '/GROUP DIRECTORY CATEGORIES/{f=1}  f && /^$/ {f++; if (f==4) $0=",;"} 1' file1
GROUP DIRECTORY CATEGORIES
datadata

Grouping Cat
datadata

datadata
,;
Above is 3rd blank line

怎么运行的:

  • /GROUP DIRECTORY CATEGORIES/{f=1}

    每当找到与 regex 匹配的行时GROUP DIRECTORY CATEGORIES,变量f就会设置为 1。

  • f && /^$/ {f++; if (f==4) $0=",;"}

    如果f不为零且当前行为空白,/^$/则加f一。如果f是 4,则将当前空行替换为,;

  • 1

    1是 awk 的 print-the-line 的神秘简写。

答案2

从根本上讲,您的方法失败了,因为您的表达式每次仅将一行读入其模式空间 - 因此它永远无法匹配多个空行(即使您可以构造适当的正则表达式)。

然而它可以使用N循环中的命令将多行读入模式空间。除了 GNU sed 的多行修饰符之外,换行符在多行模式空间中表示为\n序列 - 因此要测试空行,您需要使用\n\n而不是^$.例如:

sed -E '
  /GROUP DIRECTORY CATEGORIES/ {
  :a                            # label the start of a loop
  $!N                            # if not at the end of file, read & append the next line
  s/((\n\n.*){2})\n\n/\1\n,;\n/ # match and capture 2 instances of successive newlines, 
                                # followed by a 3rd; if found, replace the 3rd by \n,;\n 
  t                             # branch out of the loop on successful replacement
  ba                            # else branch back to label 'a'
  }' file1

在 GNU sed 中,该t;ba序列可以替换为Ta

答案3

这种复杂的寻址要求正是ex(or vi) 真正发挥作用的地方。

ex是一个POSIX 指定工具vi这是(“可视化编辑器”)的前身。值得注意的是,所有 -style 命令在 Vim 中ex仍然可用。vi

在或 Vim 中,假设您想要从文档开头开始vi第一个实例,您可以按如下方式执行此操作:/pattern/

  • vi file.txt通过键入并按在命令行上打开文件<Enter>

  • 键入以下内容,包括前导冒号。然后按<Enter>

    :0/GROUP DIRECTORY CATEGORIES//^$//^$//^$/s/^/,;/
    
  • :x键入并按 来保存更改<Enter>

在上面的命令中,小写之前的所有内容s都只是一个地址。该s命令应该非常明显。

地址的意思是,“从文件的最开始(行‘0’)开始,‘GROUP DIRECTORY CATEGORIES’的第一个实例,从那里开始一个空行的第一个实例,然后是一个空行的下一个实例,然后是下一个,然后运行替代命令。”

还有很多其他方法可以将其分开;它不一定是单衬。

您还可以使用以下ex命令完成此编辑:

0/GROUP DIRECTORY CATEGORIES/
/^$/
//
//
s//,;/
x

相关内容