grep"。*"与有效匹配不匹配?

时间:2017-01-12 21:02:01

标签: bash shell grep

信息和问题

我现在正在学习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.txta2.txt应与正则表达式匹配,但它不起作用。 但是如果我试过

ls -a | grep -E -e ^a.*
ls -a | grep -E -e a.+

这两个命令都按我的预期工作,所有文件名都匹配。

a.txt  
a1.txt
a2.txt

我无法弄清楚出了什么问题?

我尝试了什么

我搜索了这些问题,有一个question与我的非常相似,但问题是扩展的grep和基本的问题,这绝对不是我的情况。

2 个答案:

答案 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.*'

也就是说,lsnot 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 命令将传递给lsgrep。 glob的结果是:

ls -a | grep -E -e a.txt

因为在全球范围内,a.*仅匹配a.txt

您需要将正则表达式放在引号中,例如

ls -a | grep -E -e 'a.*'