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
regex in bash expression
提问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
Your regular expression matches the string starting with the first quotation mark (before
ab
) and ending with the last quotation mark (afteref
). This is greedy, even though your intention was to use a non-greedy match (*?
). It seems that bash uses POSIX.2 regular expression (check yourman 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.
I don't understand what you mean. If you want to find all matches (and there are two occurrences of
b
here), I think you cannot do it with a single~=
match.
您的正则表达式匹配以第一个引号(before
ab
)开头并以最后一个引号(afteref
)结尾的字符串。这是贪婪的,即使您的意图是使用非贪婪匹配 (*?
)。bash 似乎使用 POSIX.2 正则表达式(检查您的man 7 regex
),它不支持非贪婪的 Kleene 星。如果您只想要
"ab"
,我建议使用不同的正则表达式:if [[ $temp_input =~ \"[^\"]*\" ]]
它明确表示您不希望在字符串中使用引号。
我不明白你的意思。如果您想找到所有匹配项(并且这里出现了两次
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