我正在尝试捕捉重复模式中最长的匹配。
do_run() {
local regex='.*((abc)+).*'
local str='_abcabcabc123_'
echo "regex=${regex}"$'\n'
echo "str=${str}"$'\n'
if [[ "${str}" =~ ${regex} ]]
then
for i in ${!BASH_REMATCH[@]}
do
echo "$i=${BASH_REMATCH[i]}"
done
else
echo "no match"
fi
}我得到以下输出:
regex=.*((abc)+).*
str=_abcabcabc_
0=_abcabcabc123_
1=abc
2=abc我试着弄到这样的东西:
regex=.*((abc)+).*
str=_abcabcabc123_
0=_abcabcabc123_
x=abcabcabc(更新:x只是表示匹配组的索引并不重要,但我需要知道检索匹配组的数字.)
更新:
阅读后评论,下面的正则表达式将工作:((abc)+)
但是,我还需要捕捉到前面的内容和((abc)+)之后的内容。
我之前没有提过,因为我认为同样的解决方案也会适用。
所以新的代码是:
do_run() {
local regex='(.*)((abc)+)(.*)'
local str='_abcabcabc123_'
echo "regex=${regex}"$'\n'
echo "str=${str}"$'\n'
if [[ "${str}" =~ ${regex} ]]
then
for i in ${!BASH_REMATCH[@]}
do
echo "$i=${BASH_REMATCH[i]}"
done
else
echo "no match"
fi
}然后得到以下输出:
regex=(.*)((abc)+)(.*)
str=_abcabcabc123_
0=_abcabcabc123_
1=_abcabc
2=abc
3=abc
4=123_我希望能够从一个匹配的组中检索abcabcabc,但也希望能够检索它之前的内容和后面的内容。
发布于 2021-02-03 08:23:55
作为一种解决办法,您可以这样做:
[STEP 101] $ cat foo.sh
v=_abcabcabc123_
if [[ $v =~ (abc)+ ]]; then
middle=${BASH_REMATCH[0]}
[[ $v =~ (.*)"$middle" ]]
before=${BASH_REMATCH[1]}
[[ $v =~ "$middle"(.*) ]]
after=${BASH_REMATCH[1]}
echo "before: $before"
echo "middle: $middle"
echo "after : $after"
fi
[STEP 102] $ bash foo.sh
before: _
middle: abcabcabc
after : 123_
[STEP 103] $发布于 2021-02-03 08:15:36
我还需要捕捉前面的内容和后面的内容((abc)+)。
为此,您通常需要对perl ( (?<!abc)((abs)+)(.*)中的某些内容)进行负面展望。
我不擅长perl regex,在启用perl的grep中,我能够做到这一点:
$ grep -oxP '(.*)(?<!abc)((abc)+)\K(.*)' <<<'_abcabcabc123_'
123_
$ grep -oP '((abc)+)' <<<'_abcabcabc123_'
abcabcabc
$ rev <<<'_abcabcabc123_' | grep -oP '(.*)(?<!cba)((cba)+)\K(.*)' | rev
_Bash没有外观,也没有perl正则表达式。考虑使用python或perl。
但是,您可以通过将regex上的部分拆分,然后读取行来使用sed,这可能更简单:
$ readarray -t lines < <(<<<'_abcabcabc123_' sed -E 's/((abc)+)/\n&\n/'); declare -p lines
declare -a lines=([0]="_" [1]="abcabcabc" [2]="123_")另一个想法:您可以使用bash展开将abc部件替换为唯一的部件,然后将其拆分到该分隔符上:
$ IFS=' ' read -r before post < <(printf "%s\n" "${str//abc/ }") ; declare -p before post
declare -- before="_"
declare -- post="123_"
# or
$ IFS='@' read -r before post < <(<<<"${str//abc/@}" tr -s '@') ; declare -p before post
declare -- before="_"
declare -- post="123_"发布于 2021-02-03 08:40:38
对于给定的输入,此正则表达式将有效:
re='^([^a]|a[^b]*|ab[^c]*)((abc)+)(.*)'
str='_abcabcabc123_'
[[ $str =~ $re ]] && declare -p BASH_REMATCH输出:
declare -ar BASH_REMATCH=([0]="_abcabcabc123_" [1]="_" [2]="abcabcabc" [3]="abc" [4]="123_")所以你可以使用:
"${BASH_REMATCH[1]}" # string before
"${BASH_REMATCH[2]}" # string containing all "abc"s
"${BASH_REMATCH[4]}" # string afterhttps://stackoverflow.com/questions/66022130
复制相似问题