我现在正在学习linux命令,只是在bash中练习grep命令
我希望匹配名称以字符开头的每个文件" a" ...非常简单的要求......据我所知,正则表达式应该类似于a.*
,但它并没有&#39按照我的想法工作。
某些文件名应匹配且不匹配。
我在Ubuntu Mate 16.04 VirtualBox终端中输入了命令。 我创建了一个名为test的文档。在测试文档中,我有三个文件,
a.txt
a1.txt
a2.txt
以下是我使用grep。
的命令ls -a | grep -E -e a.*
但输出只是
a.txt
我认为.*
应该表示任意数字的任何数字。因此a1.txt
和a2.txt
应与正则表达式匹配,但它不起作用。
但是如果我试过
ls -a | grep -E -e ^a.*
ls -a | grep -E -e a.+
这两个命令都按我的预期工作,所有文件名都匹配。
a.txt
a1.txt
a2.txt
我无法弄清楚出了什么问题?
我搜索了这些问题,有一个question与我的非常相似,但问题是扩展的grep和基本的问题,这绝对不是我的情况。
答案 0 :(得分:2)
使用更多quotes!
使用您在问题中运行的文字命令:
ls -a | grep -E -e a.*
...您的 shell 会将a.*
替换为当前目录中与a.*
匹配的文件名列表glob pattern grep
什么都开始了。 (另请参阅完整的bash-hackers page on globbing)。
如果a.*
放在引号内,如:
ls -a | grep -E 'a.*'
...然后这个字符串将不再被评估为glob。您可能还希望使用^
锚定正则表达式,仅在开头搜索:
ls -a | grep -E '^a.*'
也就是说,ls
是not a tool build for programmatic use - 它不能保证以未修改的文字形式发出文件名,因此不确定是否会发出所有可能的名称grep
或其他工具正确解析它们的方式(事实上,ls
无法发出所有可能的名称是字面形式,因为它使用了换行符之间的换行符名称,而换行文字实际上可能在名称本身内)。考虑using find
进行此类处理:
while IFS= read -r -d '' filename; do
printf 'Found file: %q\n' "$filename"
done < <(find . -regex '/^a[^/]*' -print0)
...甚至可以处理具有故意难以处理名称的文件;例如,考虑mkdir -p $'\n/etc/passwd\n' && touch $'\n/etc/passwd\n/a.txt'
。
答案 1 :(得分:2)
您误解了shell如何解析命令。当你这样做时:
ls -a | grep -E -e a.*
shell 命令将传递给ls
或grep
。 glob的结果是:
ls -a | grep -E -e a.txt
因为在全球范围内,a.*
仅匹配a.txt
。
您需要将正则表达式放在引号中,例如
ls -a | grep -E -e 'a.*'