![可以将锚点 ^ $ 与 ls 一起使用吗?](https://linux22.com/image/119791/%E5%8F%AF%E4%BB%A5%E5%B0%86%E9%94%9A%E7%82%B9%20%5E%20%24%20%E4%B8%8E%20ls%20%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8%E5%90%97%EF%BC%9F.png)
锚点只能与 grep 一起使用还是可以与其他命令一起使用?
例如:
ls -l ^cat
答案1
正则表达式锚点(例如^
和 )$
仅由以下工具解析实施常用表达。 ls
不是这样的工具,所以不,它不能使用它们。然而,从 shell 调用的任何二进制文件都可以使用 shell 通配符,这是一种更简单但功能较弱的基于通配符的搜索机制。
例如,对于名称以 cat 开头的所有文件的列表:
$ ls cat* # lists all files with names which start with 'cat'
$ ls *dog # lists all files with names which end with 'dog'
$ ls d*y # Lists all files which names which start with 'd' and end
with 'y', e. g. 'donkey'
$ ls p?g # Lists all files which start with 'p', have one additional
character, and end with 'g', e. g. 'pig' and 'pug'
出于通配目的,*
表示“零个或多个字符”; while 的?
意思是“恰好是一个字符”。
答案2
该/bin/ls
程序 - 就像任何其他程序一样 - 不处理*
模式。通配符是由Unix shell,而不是它们正在运行的程序。让我解释一下。
该ls
程序(有几个实现自由软件,就像 GNU 中的那样核心工具包,因此请随意研究其源代码)得到字符串序列(作为第二个参数它是 main
函数)已被扩大通过你的外壳(经常bash
)。这并不特定于ls
,对于您的 shell 启动的每个程序都是如此(通常通过使用您的小路)。
例如,在包含a.c
, a.o
, b.c
, d.c
,e.h
文件的目录中,该ls *.c
命令被展开通过外壳进入ls a.c b.c d.c
so (在这种情况下)ls
得到 4 个参数:第一个(索引 0 的)是ls
,第二个(索引 1 的)是a.c
等等...,第四个(索引 3 的)是d.c
。所以ls
程序从没见过 *.c
外壳是执行(2)- 用四个参数来处理它。由 shell 完成的程序参数扩展称为通配。读全局(7)并了解IFS
外壳变量。
(请注意,在某些情况下,启动像你这样的文件$HOME/.bashrc
可能定义ls
为一些别名;然后替换ls
为\ls
orcommand ls
或/bin/ls
以避免此类别名扩展(后两者也可用于规避ls
重新定义为功能))
理解扩展发生的一个非常有用的技巧是首先使用自动完成shell 的功能(例如使用您的TAB密钥),或将命令(在您的情况下ls
)替换为echo
.
所以你真正想要的是具有扩展通配符的 shell。您可以找到几个,并且您可以编写自己的 shell 来执行此操作:
韋斯特有非常不同的扩展(你可以在Scheme中编码)
或者改编现有的 shell(大多数是免费软件,您可以研究其源代码)来满足您的需求,或者编写您自己的 shell。
FWIW,sash
是一个非常简单且小的 shell(有点 bug),其源代码很容易阅读。
与 Posix shell 类似巴什, - 以及其他人,例如鱼- 您可以使用命令替换,例如使用查找(1)(甚至一些ls
管道式的到 some 中grep
,就像ls -l $(ls | grep '^foo')
这有点无用,并且在某些情况下不起作用,例如带有空格或换行符的文件名,因为与ls -l foo*
) 相同。
有些命令会与某些命令进行通配(通常是引) 参数或数据,例如查找(1);你可以编写这样的程序,例如使用全局(3)或者词表达式(3)。顺便说一句,您可以使用正则表达式(由正则表达式(1)等等...)也在你的程序中,与正则表达式(3)功能。
请注意,编写自己的 shell 是一项非常有趣的练习,我强烈建议您尝试一次。您需要学习如何使用系统调用(2),例如通过阅读一些书,例如高级Linux编程,并实现您自己的通配符。并理解(在跟踪(1)) 什么系统调用由一些 shell 完成也是值得的。
实际上,如果ls ^cat
意味着列出名称以您开头的所有文件,cat
只需ls cat*
在 shell 中键入命令即可。
顺便说一句,我真的更喜欢zsh
作为我的交互的shell(因为恕我直言,它的自动补全效果更好,而且它的扩展扩展确实很有用),但这是一个品味问题,所以 YMMV。但你可以尝试一下(如果你采用它,请使用以下命令更改你的登录 shellchsh(1))。
最后,我建议避免在您自己的文件名中使用空格(以及换行符、控制字符和大多数标点符号)(因此只需使用拉丁字母和数字、点.
、百分号%
、下划线_
、加号+
、非开头的破折号-
或波浪号~
...),但是,在编写供其他人一般使用的 shell 脚本时,请考虑带有空格和奇怪字符的文件名。使用"$@"
在这样的脚本中那就更好了。
附言。据传在 Windows(我不知道)上情况有所不同,并且通配符将由一些启动代码来完成crt0或者也许在你的main
.你可以阅读操作系统:三个简单的部分以获得更广阔的视野。
答案3
正如其他人所解释的,ls
不提供对正则表达式的支持。但是,可以列出与 GNU 特定正则表达式匹配的文件find
,如下所示。
首先,您可以使用以下ls
操作:
find * -maxdepth 0 -regex "ANY_REGEX" -ls
您还可以使用该-exec
操作,它允许您使用任何命令:
find * -maxdepth 0 -regex "ANY_REGEX" -exec ls -la {} \+
最后,您可以find
与结合使用xargs
,例如:
find * -regex "ANY_REGEX" -print0 | xargs -0 ls -la
默认情况下,find
将搜索所有子目录,这就是为什么,为了复制 的行为ls
,我添加了过滤器-maxdepth 0
。
上一个示例中的操作和选项对于处理包含空格的文件名-print0
是必需find
的-0
。xargs
感谢@ilkkachu 指出这一点。
答案4
您可以使用正则表达式“with” ls
,但必须将它们传递给grep
.
ls | grep ^cat | xargs -r ls -l
Bash 仅通过比较运算符支持正则表达式=~
,这需要一个if
子句和一个for
循环。
for x in *; do if [[ "$x" =~ ^cat ]]; then ls -l "$x"; fi; done