3

这是大学时提出的问题。

问题是:列出文件testfiles夹内所有没有扩展名的文件/目录。
给出的正确答案是这样的:

ls testfiles | grep -v "\."

现在,只是为了了解ls正则表达式的工作原理,有人可以向我解释一下ls仅使用 regex 是如何工作的吗?此外,我将不胜感激任何也使用美元符号的示例$,以明确说明名称以.[a-z].

任何帮助,非常感谢。

还有一件事!这个问题的另一个答案是使用:

ls testfiles | grep "^[^.]*$"

这是怎么读的?我是这样读^[^.]*$的:

^      -> does not contain
[^.]   -> starts with a dot
*      -> repeated zero or more times
$      -> till the end

我希望有人对此进行纠正...谢谢!

4

4 回答 4

3

Unix 实用程序旨在用作过滤器,因此给出的答案是有道理的,因为它最接近现实世界的应用程序。

不过,您确实明白,它grep "\."与“句号”(因此,扩展名)匹配所有内容,并grep -v "\."匹配其他所有内容(即补码)。

很难使命令比它已经是更精确,因为谁能说什么是扩展,什么不是?


第2部分:ls testfiles | grep "^[^.]*$"

方括号表达式是由 [ 和 ] 括起来的字符列表。它匹配该列表中的任何单个字符;如果列表的第一个字符是插入符号 ^,则它匹配不在列表中的任何字符。例如,正则表达式 [0123456789] 匹配任何单个数字。

http://unixhelp.ed.ac.uk/CGI/man-cgi?grep

所以^[^.]*$实际上意味着:

任何以字符串开头和结尾的字符串,每个字符串都不是句点。

第一个插入符号不是否定,它意味着开始。第二个插入符号是“非”能指。

于 2013-03-25T00:14:02.217 回答
3

更正:

^      -> pattern starts at the beginning of the string
[^.]   -> matches something that is not a dot
*      -> repeated zero or more times
$      -> and must continue to match (only non-dot items) until the end

因此,它必须从头到尾只有非点的东西。

于 2013-03-25T00:16:26.217 回答
3

现在,只是为了了解 ls 正则表达式是如何工作的,有人可以向我解释一下这将如何通过仅使用 ls 来完成?

您可以使用忽略标志来做到这一点:

ls -I '*.*'

注意 - 适用于 CentOS 6,不确定其他 Linux 发行版。

于 2013-03-25T00:26:20.010 回答
0

标记了问题,因此您不需要 grep:

shopt -s extglob
(cd testfiles && ls -d !(*.*))

http://www.gnu.org/software/bash/manual/bashref.html#Pattern-Matching

于 2013-03-25T00:37:22.447 回答