【问题标题】:Match X or Y in grep regular expression在 grep 正则表达式中匹配 X 或 Y
【发布时间】:2020-10-16 08:05:51
【问题描述】:

我正在尝试运行一个相当简单的正则表达式来清除一些主目录。背景:我试图要求我系统上的用户清除他们不必要的文件以清理他们的主目录上的空间,所以我想用诸如 Anaconda / Miniconda 安装脚本之类的脚本通知用户,他们可以将其清除。

为了生成可能需要此类电子邮件的用户列表,我尝试运行一个简单的正则表达式来列出包含此类安装脚本的所有主目录。所以我的假设是以下就足够了:

for d in $(ls -d /home/); do
    if $(ls $d | grep -q "(Ana|Mini)conda[23].*\.sh"); then
        echo $d;
    fi;
done;

但是在运行这个之后,它完全没有结果,很遗憾。看了一会儿,我注意到grep 并没有像我期望的那样解释正则表达式。以下:

echo "Lorem ipsum dolor sit amet" | grep "(Lorem|Ipsum) ipsum"

根本没有匹配结果。这将解释为什么上面的 forloop 也不起作用。

那么我的问题是:是否可以匹配指定的正则表达式(Ana|Mini)conda[23].*\.sh,就像匹配https://regex101.com/r/yxN61p/1 中的字符串一样?或者是否有其他方法可以使用 bash 中的简单 for 循环来查找在其 homedir 中有此类文件的所有用户?

【问题讨论】:

  • 请注意,您可能正在重新发明find 命令

标签: regex bash shell for-loop sh


【解决方案1】:

您根本不需要lsgrep

shopt -s extglob

for f in /home/*/@(Ana|Mini)conda[23].*.sh; do
  echo "$f"
done

启用extglob 后,@(Ana|Mini) 匹配AnaMini

【讨论】:

    【解决方案2】:

    简短回答:grep 默认为基本正则表达式 (BRE),但未转义的 ()| 是扩展正则表达式 (ERE) 的一部分。作为扩展,GNU grep 支持交替(从技术上讲,这不是 BRE 的一部分),但您必须转义 \

    grep -q "\(Ana\|Mini\)conda[23].*\.sh"
    

    或者您可以表明您要使用 ERE:

    grep -Eq "(Ana|Mini)conda[23].*\.sh"
    

    更长的答案:这一切都在说,你不需要grep,并且解析ls的输出带有很多pitfalls。相反,您可以使用 glob:

    printf '%s\n' /home/*/*{Ana,Mini}conda[23]*.sh
    

    如果我正确理解意图,应该这样做。

    这使用了这样一个事实,即printf 只是重复其格式化字符串,如果提供的参数多于格式化指令,则将每个文件打印在单独的行上。

    /home/*/*{Ana,Mini}conda[23]*.sh 使用brace expansion,即它首先扩展为

    /home/*/*Anaconda[23]*.sh /home/*/*Miniconda[23]*.sh
    

    然后每个都用filename expansion 扩展。 [23] 的工作方式与正则表达式相同; * 是“零个或多个除/ 之外的任何字符”。

    如果您不知道要查找的文件在目录树中的深度,可以使用globstar**

    shopt -s globstar
    printf '%s\n' /home/**/*{Ana,Mini}conda[23]*.sh
    

    ** 匹配所有文件和零个或多个子目录。

    最后,如果你想处理不匹配的情况,你可以设置shopt -s nullglob(如果不匹配则扩展为空)或shopt -s failglob(如果不匹配则错误)。

    Shell 模式描述为here

    【讨论】:

    • 非常感谢您的回答!我从未见过 printf 以这种方式使用,是否有任何地方可以阅读有关 glob 的更多详细信息?
    • @Joeytje50 我会添加一些参考资料。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多