为什么找不到 -regex 匹配换行符?

ter*_*don 8 find filenames quoting regular-expression newlines

为什么这会失败?

touch "$(printf "a\nb")"; find . -regex './.\n.'
Run Code Online (Sandbox Code Playgroud)

我也试过这些,没有一个工作:

find . -regextype posix-extended -regex '.\n.'
find . -regextype posix-awk -regex '.\n.'
find . -regextype posix-basic -regex '.\n.'
find . -regextype posix-egrep -regex '.\n.'
Run Code Online (Sandbox Code Playgroud)

它似乎工作的唯一方法是(感谢@MichaelMrozek)

find . -regex './.'$'\n''.'
Run Code Online (Sandbox Code Playgroud)

至少可以说这很麻烦。那么,为什么 find 的正则表达式似乎无法处理\n呢?


更新回应到目前为止的答案:

OK,我明白,\n是不是ERE的一部分,这是我的误解,但一个find声称支持posix-awk和双方gawkmawk比赛\n如预期:

$ printf "f1l1\nhas newline:f2l1#f1l2 does not:f2l2#" | 
    mawk -F: 'BEGIN{RS="#"}; ($1~/\n/){print $1}' 
f1l1
has newline
Run Code Online (Sandbox Code Playgroud)

我没有纯粹awk的测试,所以也许 POSIXawk不匹配?否则find实际上是不是在实现posix-awk正则表达式?

Gil*_*il' 16

因为 GNU find 不支持\n作为转义序列。正则表达式\n匹配字符n。GNU find 复制了传统的 Emacs 语法,它也没有此功能¹。

虽然 GNU find 支持其他正则表达式语法,但都不支持反斜杠字母或反斜杠八进制来表示控制字符。您需要在参数中逐字包含控制字符。

周围有许多不同的正则表达式语法。POSIX基本正则表达式(BRE) 和扩展正则表达式(ERE)都不包含\n或反斜杠八进制转义。当后面没有未定义的特殊字符时,这两个定义都保留了反斜杠的含义。工具awksed都支持\n表示换行;这是特定于这些实用程序的(并且很常见,但正如您所见并不普遍)。

从 shell 脚本,您可以编写

find . -regex $'./.\n.'     # ksh/bash/zsh only
find . -regex './.
.'
find . -name '*
*'
Run Code Online (Sandbox Code Playgroud)

¹非常合乎逻辑:对于交互式使用,您可以使用C-q;键入任何字符。对于编程使用,\n作为字符串文字语法的一部分存在。


bab*_*bot 7

您不能将换行符与'\n'匹配,因为它在正则表达式中没有特殊含义(例如换行符),但您可以使用$正则表达式匹配行尾

  • @terdon 好吧,除了您尝试匹配字符 0x0A(换行符),并且您尝试使用字符序列 0x5C(反斜杠)0x6E(n)进行匹配。由于 \n 没有特殊含义,它会尝试匹配自身。\ 可能会或可能不会被删除(无效转义),具体取决于 RE 引擎,但您尝试匹配 <NL> 与 \n 或 n,两者都不匹配。 (2认同)
  • @terdon 在您的 Perl 示例中,实际发生的是字符串解析将 `\n` 转换为 <NL>,然后再将其传递给正则表达式引擎。这是 Perl 字符串解析的一个特性。 (2认同)