Wildcard Asked: 2019-01-08 19:00:16 +0800 CST2019-01-08 19:00:16 +0800 CST 2019-01-08 19:00:16 +0800 CST 搜索三个连续的换行符? 772 我知道可以使用压缩多个空行cat -s(并且可以使用压缩所有空行tr -s '\n'),但我很好奇如何在输入流中搜索此条件。 我以为stream-of-input | grep -qz $'\n\n\n'这样可以,但事实并非如此。 有没有办法用简单的工具来做这个搜索? 换句话说,如果三个连续的字节是换行符,则读取输入并以零状态退出,或者如果在没有找到三个连续的换行符的情况下达到 EOF,则以非零状态退出。 grep search 2 个回答 Voted Best Answer Michael Homer 2019-01-08T19:28:02+08:002019-01-08T19:28:02+08:00 您可以使用tr将流转换为可以正常使用 grep 的流: stream | tr 'x\n' '\0x' | grep -qz xxx 这会将所有x字节转换为空字节,并将所有换行字节转换为xs,这可以像往常一样被 grep 出。也就是说,它沿着 linefeed -> x -> null 路径移动了一步,因此三个换行符的序列现在将是三个xs 的序列,并且不会出现其他x字节(它们将成为 null 终止行的grep) . 这适用于 POSIXtr,但grep -z它是一个扩展。您可能不需要它 - 这里不需要分离行为 - 大多数greps 将处理二进制数据,但POSIXgrep只需要处理文本文件,因此您将依赖于一种或另一种扩展。 如果你的真实数据是一个文本文件,或者只是不依赖于二进制安全的行为,你可能只能依靠 stream | tr 'x\n' '\nx' | grep -q xxx - 也就是说,只是交换两个字节。这几乎与 POSIX 兼容,但实际上几乎可以在任何地方工作(问题是最后一行不会正确终止,因此它不是文本文件,因此grep不严格要求接受它)。 在任何一种情况下,一个可能的问题是没有现有x字节的文件将被视为一个很长的行,这可能超出您的grep实现将处理的限制。选择另一个预期的公共字节可能会解决这个问题。 我很惊讶您的原始grep -qz $'\n\n\n'命令不起作用,但它对我来说有一个误报问题- 它似乎表现得像grep -qz ''并且总是匹配。我不确定为什么会这样。 thrig 2019-01-08T19:27:55+08:002019-01-08T19:27:55+08:00 lex(或flex)可以处理这个问题,例如以下内容保存到tresn.l带有额外规则的文件中,主要是为了防止默认输出到标准输出(你可能想要那个?) %% \n\n\n { exit(0); } <<EOF>> { exit(1); } \n\n { ; } \n { ; } . { ; } %% 用隐式make规则编译并加入libfl* $ CFLAGS=-lfl make tresn lex -o lex.tresn.c tresn.l cc -lfl -o tresn lex.tresn.c -ll rm -f lex.tresn.c $ printf "\n\n" | ./tresn ; echo $? 1 $ printf "\n\n\n" | ./tresn ; echo $? 0 在某些系统上,您可能需要添加或-L/opt/local/lib诸如隐藏在供应商编译空间之外的某些端口或软件包系统下。CFLAGSLDFLAGSlibfl*
您可以使用
tr
将流转换为可以正常使用 grep 的流:这会将所有
x
字节转换为空字节,并将所有换行字节转换为x
s,这可以像往常一样被 grep 出。也就是说,它沿着 linefeed -> x -> null 路径移动了一步,因此三个换行符的序列现在将是三个x
s 的序列,并且不会出现其他x
字节(它们将成为 null 终止行的grep
) .这适用于 POSIX
tr
,但grep -z
它是一个扩展。您可能不需要它 - 这里不需要分离行为 - 大多数grep
s 将处理二进制数据,但POSIXgrep
只需要处理文本文件,因此您将依赖于一种或另一种扩展。如果你的真实数据是一个文本文件,或者只是不依赖于二进制安全的行为,你可能只能依靠
- 也就是说,只是交换两个字节。这几乎与 POSIX 兼容,但实际上几乎可以在任何地方工作(问题是最后一行不会正确终止,因此它不是文本文件,因此
grep
不严格要求接受它)。在任何一种情况下,一个可能的问题是没有现有
x
字节的文件将被视为一个很长的行,这可能超出您的grep
实现将处理的限制。选择另一个预期的公共字节可能会解决这个问题。我很惊讶您的原始
grep -qz $'\n\n\n'
命令不起作用,但它对我来说有一个误报问题- 它似乎表现得像grep -qz ''
并且总是匹配。我不确定为什么会这样。lex
(或flex
)可以处理这个问题,例如以下内容保存到tresn.l
带有额外规则的文件中,主要是为了防止默认输出到标准输出(你可能想要那个?)用隐式
make
规则编译并加入libfl*
在某些系统上,您可能需要添加或
-L/opt/local/lib
诸如隐藏在供应商编译空间之外的某些端口或软件包系统下。CFLAGS
LDFLAGS
libfl*