Macos Bash:使用数组参数扩展来包含匹配模式的项

Macos Bash:使用数组参数扩展来包含匹配模式的项,macos,bash,pattern-matching,Macos,Bash,Pattern Matching,我希望在数组上使用bash参数扩展来包括与给定模式匹配的项,而不是排除它们 下面是一个排除与ba*匹配的项目的示例: ar=( foo bar baz qux ) for i in ${ar[@]##ba*}; do echo "$i" done # foo # qux 这很好,但在本例中,我实际上只想包括与ba*匹配的项 以下是我尝试过的,坦率地说,我不太确定如何解释结果: ar=( foo bar baz qux ) #shopt -s extglob # seems to h

我希望在数组上使用bash参数扩展来包括与给定模式匹配的项,而不是排除它们

下面是一个排除与
ba*
匹配的项目的示例:

ar=( foo bar baz qux )
for i in ${ar[@]##ba*}; do
    echo "$i"
done

# foo
# qux
这很好,但在本例中,我实际上只想包括与
ba*
匹配的项

以下是我尝试过的,坦率地说,我不太确定如何解释结果:

ar=( foo bar baz qux )
#shopt -s extglob  # seems to have no effect either way
for i in ${ar[@]##!(ba*)}; do
    echo "$i"
done

# ar
# az
在这种情况下,我似乎得到了正确的项目,但它们的值被屏蔽了

以下是我目前的工作解决方案:

ar=( foo bar baz qux )
for i in ${ar[@]}; do
    if [[ "$i" =~ ba* ]]; then
        echo "$i"
    fi
done

# bar
# baz
我使用的是Mac OSX,并用Mac捆绑的bash 3.2.51以及安装了bash 4.2.45的自制软件进行了测试

谢谢

编辑

@casc(正确地)建议在下面重新添加从匹配中删除的“b”,但这并不是我想要的

我的实际用例更像是包含符合
*ba*
的项目,而不仅仅是
ba*
。关键是我不一定知道完整的字符串,只是它肯定会在某个地方有模式
ba*
。这可能是一个更好的例子:

ar=( foo zoobar waybaz qux )
for i in ${ar[@]}; do
    if [[ "$i" =~ ba* ]]; then
        # do something with $i
    fi
done

# zoobar
# waybaz

从数组的每个元素中,删除与
ba*
不匹配的最长前缀

  • 对于
    foo
    qua
    ,整个字符串不匹配
  • 对于
    bar
    baz
    b
    ba*
    不匹配,但
    ba
    匹配,因此只删除
    b

  • 为什么不简单地再次在切断的
    b
    上加上前缀呢

    (
    shopt -s extglob
    ar=( foo bar baz qux )
    for i in ${ar[@]/#!(ba*)}; do
       echo "b${i}"
    done
    )
    
    # ... or ...
    
    (
    export IFS=""
    ar=( foo bar baz qux )
    ar=( ${ar[@]/#!(ba*)} )
    ar=( ${ar[@]/#/b} )
    echo ${!ar[*]}
    printf '%s\n' "${ar[@]}"
    )
    
    其他备选方案包括:

    ar=( foo bar baz qux )
    printf '%s\n' "${ar[@]}" "${ar[@]##ba*}" | sort | uniq -u
    printf '%s\n' "${ar[@]}" "${ar[@]/#ba*}" | sort | uniq -u
    
    
    # alternative to current working solution 
    (
    array=( foo bar baz qux )
    for item in "${ar[@]}"; do
       case "$item" in
          ba*) echo "$item";;
            *) :;;
       esac
    done
    )
    

    啊,这是有道理的。那么你知道有没有一种方法可以实现我想要的参数展开?似乎用bash是不可能的。我在${(M)ar:#ba*}中看到了我想要用zsh实现的东西,我想这就是我的想法。谢谢你的输入。前两个解决方案依赖于了解所有已删除的字符,因此如果我尝试用
    *ba*
    替换
    *ba*
    ,它们将无法正常工作。最后三个解决方案在开始时使用通配符,但是
    printf
    s没有给我太多的灵活性。最后一个解决方案兼顾了这两个方面的优点,但在shell中开关语法非常难看——与我的工作解决方案相比,这似乎是一个横向移动。出于好奇,你的帕伦积木是干什么用的?这是局部变量的作用域吗?