bash 表达式中的正则表达式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18738576/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 06:32:19  来源:igfitidea点击:

regex in bash expression

regexbashexpression

提问by android_su

I have 2 questions about regex in bash expression.

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

1.non-greedy mode

1.非贪婪模式

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

The result is

结果是

"a1b", "d" , "45"

In java

在 Java 中

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

I can get the result below.

我可以得到下面的结果。

"a1b"
"d"
"45"

But how can I use non-greedy mode in bash?
I can understand why the \"[^\"]\" works.
But I don't understand why does the \".
?\" do not work.

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

2.global matches

2.全球匹配

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

How can I get all the matches?
ps:I only wanna use regex.

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

For the second question, sorry for the confusing.
I want to echo "b" and "b", not count "b".

对于第二个问题,抱歉让您感到困惑。
我想回声“b”和“b”,而不是“b”。

Help!

帮助!

回答by konsolebox

For your first question, an alternative is this:

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

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

For your second question, you can do this:

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

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

Or for convenience place it on a function:

或者为了方便把它放在一个函数上:

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

count_matches abcba b

Both produces output:

两者都产生输出:

2 b

Update:

更新:

If you want to see the matches you can use a function like this. You can also try other regular expressions not just literals.

如果您想查看比赛,您可以使用这样的功能。您还可以尝试其他正则表达式,而不仅仅是文字。

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

Example:

例子:

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

> find_matches abcbaaccbad 'a.'
> echo "${MATCHES[@]}"
ab aa ad

回答by nickie

  1. Your regular expression matches the string starting with the first quotation mark (before ab) and ending with the last quotation mark (after ef). This is greedy, even though your intention was to use a non-greedy match (*?). It seems that bash uses POSIX.2 regular expression (check your man 7 regex), which does not support a non-greedy Kleene star.

    If you want just "ab", I'd suggest a different regular expression:

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

    which explicitly says that you don't want quotation marks inside your strings.

  2. I don't understand what you mean. If you want to find all matches (and there are two occurrences of bhere), I think you cannot do it with a single ~=match.

  1. 您的正则表达式匹配以第一个引号(before ab)开头并以最后一个引号(after ef)结尾的字符串。这是贪婪的,即使您的意图是使用非贪婪匹配 ( *?)。bash 似乎使用 POSIX.2 正则表达式(检查您的man 7 regex),它不支持非贪婪的 Kleene 星。

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

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

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

  2. 我不明白你的意思。如果您想找到所有匹配项(并且这里出现了两次b),我认为您不能用单个~=匹配项来完成。

回答by user251764

This is my first post, and I am very amateur at bash, so apologies if I haven't understood the question, but I wrote a function for non-greedy regex using entirely bash:

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

regex_non_greedy () {
    local string=""
    local regex=""
    local replace=""

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

    printf "%s" "$string"
}

Example invocation:

示例调用:

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

Which returns:

返回:

all cats are white and white