我有一个文件如下:
示例.txt
-1
15
1 0 0 11 -1.0000E+001 1.0000E+001 -1.0000E+001
2 0 0 11 1.0000E+001 1.0000E+001 -1.0000E+001
...
29 0 0 11 1.0000E+001 2.0000E+001 1.0000E+001
30 0 0 11 5.0000E+000 5.0000E+000 5.0000E+000
-1
#ffafsda
-1
780
1 116 1 2 1 1 7 20
1 11 2 15 4 18 3 12
13 16 22 19 5 24 9 29
8 27 6 23
-1
asfasd
afsdasdf
它由始终以完全匹配的行开始和结束的块组成^ {4}-1$
。我需要通过这些块将一个文件分成多个。
我现在想到的是提取这些块的多行正则表达式:
grep -Pzo '(?s)((?m:^)\s{4}-1(?m:$).*?(?m:^)\s{4}-1(?m:$))' example.txt
输出:
-1
15
1 0 0 11 -1.0000E+001 1.0000E+001 -1.0000E+001
2 0 0 11 1.0000E+001 1.0000E+001 -1.0000E+001
...
29 0 0 11 1.0000E+001 2.0000E+001 1.0000E+001
30 0 0 11 5.0000E+000 5.0000E+000 5.0000E+000
-1 -1
780
1 116 1 2 1 1 7 20
1 11 2 15 4 18 3 12
13 16 22 19 5 24 9 29
8 27 6 23
-1
您看到第二个匹配项完全打印在第一个匹配项后面(没有换行符或分隔符) - 我无法将这些事件分离到文件中
所需的输出如下:
文件1:
-1
15
1 0 0 11 -1.0000E+001 1.0000E+001 -1.0000E+001
2 0 0 11 1.0000E+001 1.0000E+001 -1.0000E+001
...
29 0 0 11 1.0000E+001 2.0000E+001 1.0000E+001
30 0 0 11 5.0000E+000 5.0000E+000 5.0000E+000
-1
文件2
-1
780
1 116 1 2 1 1 7 20
1 11 2 15 4 18 3 12
13 16 22 19 5 24 9 29
8 27 6 23
-1
任何帮助表示赞赏。
使用
-z
(非标准 GNU 扩展),grep
适用于 NUL 分隔记录,它不是多行 grep 1,因此:-o
非标准 GNU 扩展)每个匹配项都输出 NUL 分隔的因此输出中的记录是分开的(实际上是分隔的)。
sed -n l
例如,如果您传递输出,您可以看到:请参阅
\000
分隔每个匹配项的 s。在这里你可以简化你的匹配:
但与其使用
grep
它-P
(对于P
erl,也是一个非标准的 GNU 扩展),您可以使用真实的东西,它有几个优点:grep
)-0
使用 NUL 分隔的记录,但这不是您想要的。你想要一个 slurp 模式,它perl
是-0777
或者,不要将整个文件作为一个整体并使用正则表达式,而是逐行读取它:
(尽管如果不全部匹配,则会给出不同的结果
-1
)。1 为此,请参阅
pcre2grep -M
(以前的pcregrep -M
),pcre2grep
这是一个随 PCRE2 一起提供的示例应用程序,GNUgrep
使用(可以使用)作为其-P
选项。另一种获取整个块的方法而不是
grep
首先,我建议使用
sed
来创建将块分割到不同的文件
然后您可以使用
csplit
命令根据模式分割文件。例子
解释:
csplit -
- 将从标准输入读取-f example
- 将文件的前缀设置为“example”(而不是默认的“xx”。每个前缀后跟一个从 00 开始的两位数字。--suppress-matched
- 抑制与模式 (/^ \{4\}-1$/
) 匹配的行。csplit
按模式执行分割(你不能告诉它第一行和最后一行,只有一个模式),所以在每个“关闭”模式之后,它将创建一个仅包含该模式的文件(因为在下面它会再次分裂)。如果您抑制该模式,则可以通过下一个标志来避免这种情况:-z
- 删除空输出文件'/^ \{4\}-1$/'
- 模式指示分割文件的位置。'{*}'
- 尽可能多次重复之前的模式它将输出它创建的每个文件的大小。
结果:2 个文件具有所需的块,但没有模式。
如果要将分隔行返回到文件(
-1
第一行和最后一行),可以使用以下命令:--suppress-matched
关于和-z
标志的进一步解释为了解释 的必要性
--suppress-matched
,我将向您展示会发生什么它创建了 4 个文件。请注意,
example01
并且example03
仅包含模式。当使用 时
--suppress-matched
,带 -1 的行将被抑制,结果将是example01
和example03
为空,因此不会被创建。您可以使用 GNU awk,它允许将正则表达式用作记录分隔符,作为定义“行”的东西。在这里,我们可以将其设置为
\n -1\n
,即一个换行符、4 个空格-1
和一个换行符。然后,由于它出现在您想要的部分的开头和结尾,因此我们本质上需要每隔一个“行”,因此我们可以在行号模 2 为 0 时打印:在您的示例上运行上述命令会生成两个包含以下内容的文件:
这确实有一个不幸的副作用,即在每个文件的开头添加一个空行。如果这是一个问题,您可以直接打印
-1
明确的内容:如果是我:
使用任何 awk: