我有以下功能:
function regex_match_2d_list {
local regex=$1
local text=$2
local groups=()
while [[ $text =~ $regex ]]; do
local group=()
for (( i=0; i<${#BASH_REMATCH[@]}; i++ )); do
group+=("${BASH_REMATCH[$i]}")
done
groups+=("${group[@]}")
text=${text#*"${BASH_REMATCH[0]}"}
done
echo "${groups[@]}"
}
我尝试做的是有一个函数,它将接收一个正则表达式和一个文本,并输出一个二维列表,列表中的每个元素都由正则表达式中的所有组组成:
pattern="^([a-z]+)\s([a-z]+)"
text="hello world
foo bar"
res=$(regex_match_2d_list "$pattern" "$text")
echo "${res[0,1]}"
如果我没有理解错的话,通过res[0,2],我应该得到“world”,因为它是第一个元素的第二组。
相反,如果我什么也没得到,有没有人能给我解释一下我在这里做错了什么?
1条答案
按热度按时间xe55xuns1#
注意:您可以通过在匹配后立即添加'declare -p BASH_REMATCH text'来自己调试这些问题。
行:
text=${text#*"${BASH_REMATCH[0]}"}
应删除匹配项。但是,匹配项不包括第二个标记后的尾随分隔符(“hello world”和“foo bar”之间的新行)。您希望更改匹配项以删除任何尾随新行。一个可能的解决方案-在模式的末尾添加新行。为了处理最后一行没有以新行结束-我将其设置为可选的(使用'?')。可以将新行附加到文本中作为替代。
第二个问题是将BASH_REMATCH传输到组(通过中间组变量)。当前代码还复制RE_BATCH的元素0,这将导致组中的条目重复。请考虑改用
groups+=(${BASH_REMATCH[@]}
。最后一个问题是对“res”的赋值。当前代码将数组“扁平化”为单个字符串。您可能希望将res作为数组获取。一种可能(但不总是安全的)是使用数组赋值res=($(regex_match...))。
最终代码: