如何捕获bash中的所有子字符串

时间:2014-03-21 07:05:03

标签: regex bash

我有一个这样的字符串: temp_input =' [a1b] hjh [d;],[45]' 。我想捕获[]对之间的所有子串(没有" ["和"]")。我用google搜索得到了这个:

temp_input='[a1b] hjh [d;] , [45]'
if [[ $temp_input =~ \[[^\]]+\] ]]
then
echo ${BASH_REMATCH[0]}                   // [a1b]
fi

如果我只能用=〜运算符获得所有匹配? 提前谢谢!

2 个答案:

答案 0 :(得分:4)

不确定。您可以动态构建正则表达式(您只需记住最长匹配正则表达式的结果):

#! /bin/bash
temp_input='[a1b] hjh [d;] , [45]'

regex='\[(.*)\]'
for (( i=0 ; i<${#temp_input}/2 ; i++ )) ; do
    regex+='.*\[(.*)\]'
    if [[ $temp_input =~ $regex ]] ; then
        matches=("${BASH_REMATCH[@]}")
    fi
done

for (( m=1; m<${#matches[@]} ; m++ )) ; do
    echo "${matches[m]}"
done

以下是如何在不使用 =~运算符的情况下执行此操作,逐个字符地迭代输入字符:

#! /bin/bash
temp_input='[a1b] hjh [d;] , [45]'

matches=()
string=''
in=0

for ((i=0 ; i<${#temp_input} ; i++)) ; do
    char=${temp_input:i:1}
    if ((in)) ; then
        if [[ $char == ] ]] ; then
            in=0
            matches+=("$string")
            string=''
        else
            string+=$char
        fi
    fi
    if [[ $char == [ ]] ; then
        in=1
    fi
done

for m in "${matches[@]}" ; do
    echo "$m"
done

或更短,使用不同类型的参数扩展+模式匹配:

#! /bin/bash
temp_input='[a1b] hjh [d;] , [45]'

matches=()
while [[ $temp_input == *\[*\]* ]] ; do
    temp_input=${temp_input#*[}
    t=${temp_input%%]*}
    matches+=("$t")
done

for m in "${matches[@]}" ; do
    echo "$m"
done

答案 1 :(得分:2)

您可以使用read 通过分隔符拆分输入字符串,并使用shell参数扩展来去除不需要的部分:

temp_input='[a1b] hjh [d;] , [45]'

while read -d ']' foo; do
  echo "${foo##*[}"
done <<< "${temp_input}"

这会产生:

a1b
d;
45

更好的是,替换

  echo "${foo##*[}"

  [[ $foo == *[* ]] && echo "${foo##*[}"

并且脚本还会处理foo]等输入。

您也可以使用grep。说grep -oP '(?<=\[)[^[]*(?=\])' input(假设您的grep版本支持PCRE)