【问题标题】:grep ".*" does not match valid matches?grep ".*" 不匹配有效匹配项?
【发布时间】:2017-01-12 21:02:00
【问题描述】:

信息和问题

我现在正在学习 linux 命令,只是在 bash 中练习 grep 命令。
我想匹配名称以字符“a”开头的每个文件......非常简单的要求......据我所知,正则表达式应该类似于a.*,但它不像我想的那样工作。

有些文件名应该匹配不匹配。

我的命令

我在 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和基本的,这绝对不是我的情况。

【问题讨论】:

  • 不是答案:使用find
  • 请考虑对代码使用代码语法(如四个文字空格,或编辑器中的 {} 按钮),而不是滚动您自己的引用文本语法和粗体的组合。
  • 另外,我希望你不要实际上打算将它与ls 一起使用,should not be used programatically
  • 不知道为什么我被否决了?错误的解释是要发生的,OP确实明确说grep,但他的要求需要find?对此有什么合理的解释吗?
  • PS:shellcheck自动识别this issue

标签: bash shell grep


【解决方案1】:

使用更多quotes

使用您在问题中运行的文字命令:

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

...您的 shell 将在grep 启动之前将a.* 替换为当前目录中与a.* 匹配的文件名列表作为glob pattern。 (另请参阅完整的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 can't 发出所有可能的名称都是文字形式,因为它在名称之间使用换行符分隔符,而换行文字实际上可能在名称本身内)。考虑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' &amp;&amp; touch $'\n/etc/passwd\n/a.txt'

【讨论】:

    【解决方案2】:

    您误解了 shell 如何解析您的命令。当你这样做时:

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

    Shell 将命令 传递给lsgrep。 glob 的结果是这样的:

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

    因为在 globbing 中,a.* 只匹配 a.txt

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

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

    【讨论】:

    • 觉得我比你领先... 20 秒?
    • @CharlesDuffy 这是题外话,这不是 [race-condition] :)
    • (也就是说,存在 这个特殊的 离题的闲聊是为了让其他人清楚为什么我不删除我的答案,尽管它包含严格重复的内容,即如果有人在我之前发布了涵盖所有相同领域的内容,我通常会做什么,并且我没有重大的改进待定,这将提高我的答案的价值或涵盖更多的领域)。
    • @CharlesDuffy 干得好!...Orz..这太快了...我没有意识到这是'ls'的问题,也许我应该更彻底地搜索它.. ..
    • @CieloWu,需要明确的是,这不是ls,尤其是在运行 any 命令之前,shell 会执行未加引号的参数的通配;命令本身无法控制该行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 2013-03-25
    • 1970-01-01
    • 2012-11-23
    • 2011-06-15
    • 2023-04-06
    • 2014-11-06
    相关资源
    最近更新 更多