gpt4 book ai didi

bash - 匹配 bash 正则表达式中的 N 个模式

转载 作者:行者123 更新时间:2023-12-02 03:28:10 24 4
gpt4 key购买 nike

我知道我可以做这样的事情:

[[ $s =~ ^(re)(re)$ ]]

用一系列括号表达式匹配项填充BASH_REMATCH数组。但有可能匹配未知数量的这些匹配吗?例如,我得到以下内容:

s='abc defghi     jklm    nop '
[[ $s =~ ^([^ ]+ +)+$ ]]
declare -p BASH_REMATCH

输出:

declare -ar BASH_REMATCH=([0]="abc defghi     jklm    nop " [1]="nop ")

我发现每次匹配时,括号内的表达式都会被重写到 BASH_REMATCH[1] 上。

我真正想看到的是:

declare -ar BASH_REMATCH=([0]="abc defghi     jklm    nop " 
[1]="abc "
[2]="defghi "
[3]="jklm "
[4]="nop ")

这可以通过单个命令实现吗?

最佳答案

这很好,但我认为对于未知数量的子表达式来说,您所要求的不可能是可能的。

像下面这样的循环可能是你最好的选择:

s='abc defghi     jklm    nop '
a=()
t="$s"

while [[ $t =~ ^([^ ]+ +) ]]; do
a+=( "${BASH_REMATCH[1]}" )
t="${t#${BASH_REMATCH[1]}}"
done

declare -p a

输出:

declare -a a=([0]="abc " [1]="defghi     " [2]="jklm    " [3]="nop ")

在不损害原始字符串的情况下,这会从字符串的开头去除模式,然后将该模式添加到结果数组中,并使用模式扩展从字符串副本的开头去除匹配。如果你想让它更优雅,你当然可以把它放在一个函数中;请记住,不能从函数返回数组,您需要使用全局数组或引用:

function ssplit() {
local -n a="$1"
local t="$2"
while [[ $t =~ ^([^ ]+ +) ]]; do
a+=( "${BASH_REMATCH[1]}" )
t="${t#${BASH_REMATCH[1]}}"
done
}

declare -a foo=()

ssplit foo "$s"

declare -p foo

输出:

declare -a foo=([0]="abc " [1]="defghi     " [2]="jklm    " [3]="nop ")

请注意,local -n 是 bash 版本 4 中引入的一项功能。

另一种可能性可能是根据字符串分析构建匹配正则表达式:

x=( $s )
printf -v pat '%s' $(printf '%.0s([^[:space:]]+[[:space:]]+)' $(seq 1 "${#x[@]}"))
[[ $s =~ $pat ]] && declare -p BASH_REMATCH

输出:

declare -ar BASH_REMATCH=([0]="abc defghi     jklm    nop " [1]="abc " [2]="defghi     " [3]="jklm    " [4]="nop ")

我不太喜欢编写代码的代码,但这似乎可行。虽然它不是单个命令,但至少它避免了 while 循环。请注意,在幕后,bash 仍在循环遍历 printf 的参数,以构建 $pat

关于bash - 匹配 bash 正则表达式中的 N 个模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52607838/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com