【问题标题】:Why does BASH_REMATCH return empty when the script file is sourced from zsh?当脚本文件来自 zsh 时,为什么 BASH_REMATCH 返回空?
【发布时间】:2020-10-19 14:45:30
【问题描述】:

所以我为自己创建了一个可爱的小 bash 脚本:

#!/usr/bin/env bash

TEXT="FOO BAR"
REGEX="FOO (.+)"

if [[ $TEXT =~ $REGEX ]]; then 
    echo "Matched ${BASH_REMATCH[1]}"
else
    echo "No match."
fi

非常基本。如果我运行./cutescript.sh,那么我会得到结果:

Matched BAR

但如果我获取脚本. ./cutescript.sh,那么它仍然匹配,但BASH_REMATCH[1 为空。

笏。

我在 MacOS Catalina 10.15.7 (19H2) 上,在 zsh 中执行此操作,但使用 bash shebang。

谁能解释这种违规行为?

【问题讨论】:

  • 顺便说一句,这就是为什么要获取的文件(与要执行的文件不同!)具有特定于 shell 的扩展名的原因。如果你. yourscript.bash,那就更清楚一点,它 only 意味着在 bash 中运行;而使用. yourscript.sh 运行的东西通过名称进行通信,它旨在与所有 POSIX-y shell 兼容(顺便说一句,zsh 不是)。
  • ...这与打算作为库加载的 Python 模块具有 .py 扩展名的方式相同,但作为脚本运行的模块根本没有扩展名(您运行pip,而不是 pip.py)。将东西作为库加载——就像source / . 所做的那样——只有当这些东西是为你已经在运行的相同语言/解释器编写时才合适。
  • 非常有意义!感谢您指出不同之处!

标签: regex bash zsh macos-catalina


【解决方案1】:

当您使用. 读取文件时,它会被您正在运行的任何shell 执行——在这种情况下,您说您在zsh 中。 BASH_REMATCH 数组的名称,顾名思义,是特定于 bash 的;例如,如果您的 shell 是 zsh,那么在这种情况下匹配的文本将在 $match[1] 中找到。而且我认为 ksh 根本不会进行真正的正则表达式匹配。

【讨论】:

  • 我认为说 .source 的缩写是倒退:source(非标准扩展名)是 . 的更长、更易读的名称(POSIX-操作的标准化、可移植名称)。
  • 感谢您指出不同之处!您的回答帮助我想出了一个解决方案,该解决方案允许脚本在 zsh 中同样工作。
  • 很高兴我能帮上忙! FWIW,整个匹配(bash 的 ${BASH_REMATCH[0]})在 zsh 的 $MATCH 中找到,因为像 $match 这样的数组在 zsh 中通常没有索引 0。
【解决方案2】:

现在,知道BASH_REMATCHzsh 中并不存在,我做了更多的挖掘工作:

这篇文章实际上是重复的。这里还有一个问题可以解释解决方案:BASH_REMATCH doesn't capture

设置选项KSH_ARRAYS BASH_REMATCH 允许zsh 模拟bash 的正则表达式功能。

使上述脚本与zsh兼容的简单方法是:

#!/usr/bin/env bash

# Ensures that BASH_REMATCH works if called in zsh.
setopt KSH_ARRAYS BASH_REMATCH

TEXT="FOO BAR"
REGEX="FOO (.+)"

if [[ $TEXT =~ $REGEX ]]; then 
    echo "Matched ${BASH_REMATCH[1]}"
else
    echo "No match."
fi

unsetopt KSH_ARRAYS BASH_REMATCH

还有另一个相关问题:What is the zsh equivalent for $BASH_REMATCH[]?

【讨论】:

    猜你喜欢
    • 2011-05-22
    • 2019-02-14
    • 2019-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 2018-07-06
    相关资源
    最近更新 更多