1

我对 bash 表达式中的正则表达式有 2 个问题。

1.非贪心模式

local temp_input='"a1b", "d" , "45"'
if [[ $temp_input =~ \".*?\" ]]
then
    echo ${BASH_REMATCH[0]}
fi

结果是

"a1b", "d" , "45"

在java中

String str = "\"a1b\", \"d\" , \"45\"";
Matcher m = Pattern.compile("\".*?\"").matcher(str);
while (m.find()) {
    System.out.println(m.group());
}

我可以得到下面的结果。

"a1b"
"d"
"45"

但是如何在 bash 中使用非贪婪模式?
我可以理解为什么 \"[^\"] \" 有效。
但我不明白为什么 \" 有效。
?\“ 不工作。

2.全局匹配

local temp_input='abcba'
if [[ $temp_input =~ b ]]
then
    #I wanna echo 2 b here. 
    #How can I set the global flag?
fi

我怎样才能得到所有的比赛?
ps:我只想使用正则表达式。

对于第二个问题,很抱歉造成混淆。
我想呼应“b”和“b”,而不是“b”。

帮助!

4

3 回答 3

3

对于您的第一个问题,另一种选择是:

[[ $temp_input =~ \"[^\"]*\" ]]

对于第二个问题,您可以这样做:

temp_input=abcba
t=${temp_input//b}
echo "$(( (${#temp_input} - ${#t}) / 1 )) b"

或者为方便起见将其放在一个函数上:

function count_matches {
    local -i c1=${#1} c2=${#2}
    if [[ c2 -gt 0 && c1 -ge c2 ]]; then
        local t=${1//"$2"}
        echo "$(( (c1 - ${#t}) / c2 )) $2"
    else
        echo "0 $2"
    fi
}

count_matches abcba b

两者都产生输出:

2 b

更新:

如果您想查看匹配项,可以使用这样的函数。您还可以尝试其他正则表达式,而不仅仅是文字。

function find_matches {
    MATCHES=() 
    local STR=$1 RE="($2)(.*)"
    while [[ -n $STR && $STR =~ $RE ]]; do
        MATCHES+=("${BASH_REMATCH[1]}")
        STR=${BASH_REMATCH[2]}
    done
}

例子:

> find_matches abcba b
> echo "${MATCHES[@]}"
b b

> find_matches abcbaaccbad 'a.'
> echo "${MATCHES[@]}"
ab aa ad
于 2013-09-11T10:36:50.067 回答
2
  1. 您的正则表达式匹配以第一个引号 (before ab) 开始并以最后一个引号 (after ef) 结尾的字符串。这是贪婪的,即使您的意图是使用非贪婪匹配 ( *?)。似乎 bash 使用 POSIX.2 正则表达式(检查你的man 7 regex),它不支持非贪婪的 Kleene 星。

    如果你想要 just "ab",我建议使用不同的正则表达式:

    if [[ $temp_input =~ \"[^\"]*\" ]]
    

    它明确表示您不希望在字符串中使用引号。

  2. 我不明白你的意思。如果你想找到所有匹配项(这里有两次出现b),我认为你不能用一个~=匹配项来做到这一点。

于 2013-09-11T10:38:15.473 回答
1

这是我的第一篇文章,我在 bash 方面非常业余,所以如果我不理解这个问题,我深表歉意,但我完全使用 bash 为非贪婪的正则表达式编写了一个函数:

regex_non_greedy () {
    local string="$1"
    local regex="$2"
    local replace="$3"

    while [[ $string =~ $regex ]]; do
        local search=${BASH_REMATCH}
        string=${string/$search/$replace}
    done

    printf "%s" "$string"
}

示例调用:

regex_non_greedy "all cats are grey and green" "gre+." "white"

返回:

all cats are white and white
于 2016-02-11T09:05:42.263 回答