我正在尝试使用 find 命令的正则表达式来使用点字符匹配换行符。这通常是通过s
修饰符来完成的;然而,不同的正则表达式引擎有不同的格式,我无法确切地弄清楚如何编写正则表达式,以便 find 命令将匹配换行符。例如,我将如何更改以下简单命令以匹配所有文件,包括名称中包含换行符的文件:
find /home/user -regex ".*"
我已经尝试过"(?s).*"
,,"/.*/s"
可能还有其他一些。
答案1
我的 GNU find 版本支持几种不同的正则表达式变体,可以使用以下命令进行选择-regextype
:
有效类型为“findutils-default”、“awk”、“egrep”、“ed”、“emacs”、“gnu-awk”、“grep”、“posix-awk”、“posix-basic”、“posix-” egrep'、'posix-extend'、'posix-minimal-basic'、'sed'。
几乎所有这些都让点匹配换行符,...除了emacs
,这是默认值。
所以,使用其他的。posix-extended
可能足够理智:
$ touch hello $'new\nline'
$ find . -type f -regex '.*'
./hello
$ find . -type f -regextype posix-extended -regex '.*'
./hello
./new?line
如果您正在跑步其他跑步find
,您的里程可能会有所不同。经过快速测试,我的 Mac 上的默认情况下确实会匹配换行符.
。
再说一次,对于简单的模式,您可以只使用-name
which 采用 shell 全局变量(并且不应该有换行符问题)。
这(?s)
看起来像是 PCRE/Perl 正则表达式的一个功能,但我不认为find
支持这一点。至于/.*/s
,find
仅采用原始模式,没有分隔符,因此没有尾随选项。
答案2
命令
find ~user
会找到所有名称,包括那些包含换行符的名称。-type f
如果您只想查找常规文件,请添加。
如果您不想限制名称匹配,请不要对名称使用测试。
要限制使用子字符串匹配的名称,您可以在-name
测试中使用通配模式。*
和都?
以通配模式匹配换行符,无论是在一般 shell 中还是在-name
的测试中find
:
使用标准的示例find
:
$ find . -name 'file?name'
./file
name
$ find . -name 'file*name'
./file
name
$ find . -name 'd*name'
./dir
name
$ echo ./d*name
./dir
name
回答被误解的问题(“如何找到包含换行符的名称”):
使用标准find
:
find ~user -name '*
*'
在支持这些的 shell 中使用“C-strings”(仍然使用标准find
)
find ~user -name $'*\n*'
GNU 中通常可用的内置正则表达式类型都无法find
将换行符与 相匹配\n
,因此您只能使用文字换行符,就像上面的通配模式一样。这意味着使用标准-name
测试可能比非便携式-regex
测试更容易。