【问题标题】:Finding strings with a specific number of letters, extensions included with grep查找具有特定数量字母的字符串,grep 包含的扩展名
【发布时间】:2016-05-25 02:53:29
【问题描述】:

如果我通过管道将ls 传递到grep,我将如何返回一个文件列表,条件是它们只有x 个字母,包括扩展名?

例如,如果ls 给我:

abcde.jav a156e.exc test.c prog1.c qwert r.c 

我正在寻找所有包含严格 5 个字母的文件,包括扩展名:

a156e.exc test.c prog1.c qwert

我试过了:

ls | grep '^[a-z]${5}'
ls | grep "^[a-z]|[a-z]$"

和其他类似的东西,但我似乎无法理解。似乎解决方案应该非常简单,但我无法弄清楚。任何帮助将不胜感激。

【问题讨论】:

  • 旁白:如果你碰巧这样做了:不要使用ls 输出任何东西。 ls 是一个交互式查看目录元数据的工具。任何用代码解析ls 输出的尝试都会被破坏。 Globs 更加简单和正确:阅读Parsing ls
  • qwerty 有 6 个字母。那不应该匹配,对吧?
  • 你可以用find代替ls
  • @JoshCrozier,你是对的,我的错。
  • @RanyAlbegWein,我不知道!我很欣赏这个链接。

标签: regex bash grep glob ls


【解决方案1】:

您可以使用以下表达式:

Live Example

^([^a-z]*[a-z][^a-z]*){5}$

说明:

  • ^ - 表示字符串开头的锚点
  • ([^a-z]*[a-z][^a-z]*) - 匹配零个或多个非字母字符之间的单个字母的组
  • {5} - 匹配上一组 5 次
  • $ - 表示字符串结尾的锚点。

用法:

ls | grep -E '^([^a-z]*[a-z][^a-z]*){5}$'

或者没有ls

for f in *; do
  if [[ $f =~ ^([^a-z]*[a-z][^a-z]*){5}$ ]]
    then
      echo $f
  fi
done

【讨论】:

  • 正是我想要的。谢谢!
  • 很棒的正则表达式。您可以避免ls,而无需诉诸(慢)循环:printf '%s\n' * | grep -E '^([^a-z]*[a-z][^a-z]*){5}$'。或者,使用进程替换:grep -E '^([^a-z]*[a-z][^a-z]*){5}$' <(printf '%s\n' *)。 (这仍然会与嵌入换行符的文件名中断;使用 GNU grep,可以通过以下方式进行补救:grep -zoE '^([^a-z]*[a-z][^a-z]*){5}$' <(printf '%s\0' *))。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 2022-09-28
  • 1970-01-01
  • 2014-10-27
相关资源
最近更新 更多