GNU sed 方式

GNU sed 方式

我有一个名为 file_a.txt 的文本文件。我的第一个命令是

grep -A 12 ".production =" file_a.txt

输出是几个块。每个字符串块包含 13 行

grep我特别想删除使用原始文件 file_a.txt 中的命令获得的所有字符串块。我不想将 grep 输出发送到新文件。我也不想使用,grep -v因为它在我的情况下不起作用。

我尝试过类似的事情,但没有任何效果:

cut < grep -A 12 ".production =" file_a.txt

sed -i '/`grep -A 12 ".production ="`/d' file_a.txt

答案1

GNU sed 方式

GNU sed(如果您使用的是某些 Linux 发行版,它应该是默认sed实现),您可以使用如下内容:

sed '/.production =/,+12d' inputfile.txt

怎么运行的:

  1. 它逐行扫描输入文件(这就是 sed 的工作原理)并检查是否应该使用该命令。
  2. 我们的命令是d(最后一个字符),这意味着删除该行。
  3. 但只有当前行与我们的范围匹配时,此命令才会运行。
  4. 该范围由两个以字符分隔的参数(包括范围的开始和结束)指定,。第一个是正则表达式/.production =/,它匹配包含该表达式的每一行。第二个参数是+12dwhich的意思12 lines from start range
  5. 因此,我们的范围匹配与表达式匹配的每一行以及接下来的 12 行并删除它们。
  6. 所有其他行都打印到输出(默认sed behaviour)。

便携,丑陋的方式

这个应该适用于其他sed实现,但涉及更多的输入并且不是那么健壮:

sed '/.production =/{N;N;N;N;N;N;N;N;N;N;N;N;d}' somefile.txt

怎么运行的:

  1. 它逐行扫描输入文件(这就是 sed 的工作原理)并检查是否应该使用该命令。
  2. 它检查该行是否与/.production =/模式匹配。如果是这样,它将运行大括号中的所有命令{}
  3. 我们运行Ncomamnd 12 次。N命令读取下一行并将其附加到当前缓冲区。因此,运行 12 次后,当前缓冲区中连接了 13 行(第一行 + 由N命令读取的 12 行)。
  4. 现在我们运行d命令来删除这串联的 13 行。
  5. sed继续,直到找到另一个模式并再次删除 13 行。所有其他行均被打印(默认sed行为)。

答案2

您可以检索要开始过滤的行号,然后使用 AWK 对其进行过滤。

在 AWK 中,NR 表示记录号,默认为行尾 (\n)。

START_LINE=$(cat file_a.txt | grep -n .production | cut -f1 -d:)
cat file_a.txt | awk '{ if(NR < '$START_LINE' || NR > '$START_LINE' + 12) print $0; }'

答案3

当 grep 和 sed 不能完全解决问题时,可以使用 awk。 awk 可以轻松模拟大多数文本实用程序(sort这是主要的例外),并且可以以比管道更灵活的方式组合它们。

awk '
    /.production =/ {skip_lines = 13}
    skip_lines {--skip_lines}
    !skip_lines {print}
' file_a.txt >file_a.txt.new &&
mv file_a.txt.new file_a.txt

答案4

您可以在 Ex 模式下使用 Vim:

ex -sc '/.production =/d13|x' file_a.txt
  1. //移动到匹配行

  2. 13选择13行

  3. d删除

  4. x保存并关闭

相关内容