我正在尝试使用此命令ls -p | egrep "\<[A-Z]+\>"
来打印所有大写文件和目录名称,其中目录名称附加有 / 。我不明白为什么我的命令有效,即使我说只 grep 所有大写字母的文件/目录名称。我得到了正确的输出,但不明白 grep 如何列出像 XXX/ 这样的目录。
答案1
我认为您的问题是“为什么DIRNAME/
匹配扩展正则表达式\<[A-Z]+\>
,即使它有一个不是大写字母(/
)的字符?”。
您的正则表达式匹配任何包含单词全部大写:
$ printf '%s\n' "this is not matched" "this IS matched" | egrep "\<[A-Z]+\>"
this IS matched
and匹配零宽度“单词边界”,即“单词字符”和不属于该类型的字符(或行的开头/结尾)之间的空格\<
。\>
单词字符是类中的任何字符[[:alpha:]_]
(字母和下划线)。
你的表达式匹配类似DIRNAME/
since的东西DIRNAME
匹配表达式(在之前D
和之后有一个单词边界E
)。
要从目录列表中过滤掉特定名称,请勿使用grep
或其他基于行的文本操作工具。文件名可以包含换行符,因此基于行的工具将很难做正确的事情,除非您对文件名施加限制。
相反,要获取目录中的所有大写名称bash
:
$ ls -p -d *
DIR/ FILE TEST123 dir/ file test123
$ ls -p -d !(*[[:lower:]]*)
DIR/ FILE TEST123
这需要shopt -s extglob
启用扩展的通配模式。扩展通配模式!(*[[:lower:]]*)
匹配任何不包含小写字母的内容。
请注意,该模式不关心/
添加到目录名称的ls -p
。这是因为模式与文件名匹配,并且不存在包含字符 的文件名/
。另外,模式也得到了扩展前 ls
被调用。
如果您还想清除包含数字的名称,请使用
$ ls -p -d !(*[[:lower:][:digit:]]*)
DIR/ FILE
(这不包括任何包含至少一个小写字母或数字的名称)或者,
$ ls -p -d !(*[[:lower:]]*|*[[:digit:]]*)
DIR/ FILE
(这不包括任何包含至少一个小写字母的名称,也不包括任何包含至少一位数字的名称)。
答案2
语法\>
意思是匹配在词尾。你想要的可能是
ls | egrep "^[A-Z.]+$"
where^
匹配行首, and$
匹配行尾。
答案3
$ ls -p | egrep "[A-Z]+"
ABC
$ ls -p ???
ABC fif out
对我来说,是单词边界匹配改变了行为。
ls -p | egrep "\<[A-Z]+\>"
在我的例子中没有给出任何输出。
比较ls -f |cat
和ls -p |cat
。当您开始调整正则表达式时,您会发现:人们不应该打扰这些东西: 太复杂了,最后不建议这么做解析系统地 ls: ls 输出只是一个“报告”,而不是与 ie 一起操作的文件列表。 (像一个截屏几乎是 MS Windows 中的“资源管理器”窗口。)
$ ls -p |cat
ABC
XYZ/
$ ls -f |cat
XYZ
ABC
甚至顺序也不同;该斜杠/
不应用于过滤目录。
它需要类似的东西find . -type d
(仅列出目录,也在所有子目录中),然后您就有了任何文件系统搜索的良好起点。
$ find . -type d
.
./XYZ
./d3
./d3/d2
./d3/d1
./d2
./d1
您的规范介于简单的 ls (可能使用 grep 技巧)和一些干净的解决方案之间find
。我不会给出任何一个 - 一切都取决于您的性格和您未来关于列出“原始”文件系统信息的计划。
这说明了差异:
$ find . -name "d1"
./d3/d1
./d1
$ ls -R |grep d1
d1
./d1:
d1
./d3/d1:
使用 ls-grep 你可以获得“额外的”行和字符。绝望之际,在shell中交互:为什么不呢? (你知道文件“d1”是某处)
但任何脚本化的东西都应该依赖find
并且它有很多可能性。它将您的文件系统变成数据库:查询和报告:两个步骤。ls
只是命令行上的快速一体化工具。
$ ls -p -d !(*[[:lower:]]*|*[[:digit:]]*)
这真的很严重吗?除了这个以外,还有一些战略建议怎么样?见评论等。
哦,也许您想参与任何用户能想到的每一款衬里。所以巴洛克式的。我我愿意根风格。