21

我正在尝试为我bash_profile添加一个函数:

function git-unpushed {
    brinfo=$(git branch -v | grep git-branch-name)
    if [[ $brinfo =~ ("[ahead "([[:digit:]]*)]) ]]
    then
        echo "(${BASH_REMATCH[2]})"
    fi
}

但我收到以下错误:

bash:预期的条件二元运算符`

bash:附近有语法错误=~'

据我所知,“等于波浪号”运算符 ( =~) 在 bash 中计算为正则表达式。

为什么会=~抛出错误?

更新:这是手动输入的屏幕截图(正在运行 sh.exe):

等于波浪号 (=~) 运算符失败的屏幕截图

4

4 回答 4

26

我在 Windows 上安装 Git 时在 Bash 3.1.0 上遇到了同样的错误。最终我将其更改为:

if echo $var | grep -E 'regexp' > /dev/null
then
  ...
fi
于 2013-06-07T15:08:15.303 回答
13

根据https://groups.google.com/forum/#!topic/msysgit/yPh85MPDyfE ,这是因为 msys 没有将 libregex 与 bash 一起提供。假设如果您编译/找到一个 msys 构建的 libregex,并将其放在库路径中,则=~可以正常工作。

于 2013-08-21T23:28:06.717 回答
7

2015 年更新:msysgit 现已过时。您应该使用git-for-windows
附带的 bash 。 正如在这个答案中提到的,它使用了一个更新的 bash (4.3+),它的语法适用。
=~


原始答案(2013 年 3 月)

使用 msysgit 打包的 bash 可能太旧而无法完全支持该运算符。
肯定是太旧了未引用的正则表达式进行比较,如“ B​​ash,版本 3 ”和“如何在 bash 脚本中使用正则表达式? ”中所述:

从 Bash 3.2 版开始,不再引用要匹配的表达式。

实际上,mklement0在评论中提到:

=~在 bash 3.0 中引入,并且始终支持 RHS 上的未引用标记。
直到 3.1.x,引用的标记被视为与未引用的标记相同:两者都被解释为正则表达式。
3.2 中的变化是带引号的标记(或标记的带引号的子字符串)现在被视为文字

但我尝试使用引号(在最新的 msysgit 1.8.1.2 中),它仍然失败:

vonc@voncvb /
$ /bin/bash --version
GNU bash, version 3.1.0(1)-release (i686-pc-msys)
Copyright (C) 2005 Free Software Foundation, Inc.
vonc@voncvb /
$ variable="This is a fine mess."
vonc@voncvb /
$ echo "$variable"
This is a fine mess.
vonc@voncvb /
$ if [[ "$variable" =~ T.........fin*es* ]] ; then echo "ok" ; fi
bash: conditional binary operator expected
bash: syntax error near `=~'
vonc@voncvb /
$ if [[ "$variable" =~ "T.........fin*es*" ]] ; then echo "ok" ; fi
bash: conditional binary operator expected
bash: syntax error near `=~'
vonc@voncvb /
于 2013-03-20T07:43:56.017 回答
1

这是一个支持提取匹配字符串的解决方案。如果 bash 不支持操作符 =~,则使用 sed 命令(与 msysgit 一起安装)

if eval "[[ a =~ a ]]" 2>/dev/null; then
    regexMatch() { # (string, regex)
        eval "[[ \$1 =~ \$2 ]]"
        return $?
    }
elif command -v /bin/sed >/dev/null 2>&1; then
    regexMatch() { # (string, regex)
        local string=$1
        if [[ ${2: -1} = $ ]]; then
            local regex="(${2%$})()()()()()()()()$"
        else
            local regex="($2)()()()()()()()().*"
        fi
        regex=${regex//\//\\/}
        local replacement="\1\n\2\n\3\n\4\n\5\n\6\n\7\n\8\n\9\n"
        local OLD_IFS=$IFS
        IFS=$'\n'
        BASH_REMATCH=($(echo "$string" | /bin/sed -rn "s/$regex/$replacement/p" | while read -r; do echo "${REPLY}"; done))
        IFS=$OLD_IFS
        [[ $BASH_REMATCH ]] && return 0 || return 1
    }
else
    error "your Bash shell does not support regular expressions"
fi

使用示例:

if regexMatch "username@host.domain" "(.+)@(.+)"; then
    echo ${BASH_REMATCH[0]}
    echo ${BASH_REMATCH[1]}
    echo ${BASH_REMATCH[2]}
fi
于 2015-10-23T09:40:58.027 回答