Bash脚本 - 使用正则表达式分隔符拆分字符串

时间:2014-04-16 16:03:41

标签: regex string bash split sh

我想分割类似于' substring1 substring2 ONCE [0,10s] substring3'的字符串。预期结果应该是(带分隔符' ONCE [0,10s]'):

substring1 substring2
substring3

问题是分隔符中的数字是可变的,例如' ONCE [0,1s]'或者' ONCE [0,3m]'或者' ONCE [0,10d]'等等。

如何在bash脚本中执行此操作?有什么想法吗?

谢谢

3 个答案:

答案 0 :(得分:3)

OP中提供的示例(以及@GlennJackman和@devnull提供的两个答案)假设实际问题可能是:

  

在bash中,如何用换行符替换字符串中正则表达式的匹配。

这与“使用正则表达式拆分字符串”实际上并不相同,除非您添加字符串不包含任何换行符的约束。即便如此,它实际上并没有“分裂”字符串;推测是其他一些过程会使用换行符来分割结果。

一旦重新提出问题,解决方案就没有挑战性。您可以使用任何支持正则表达式的工具,例如sed

sed 's/ *ONCE\[[^]]*] */\n/g' <<<"$variable"

(如果您只想替换第一个序列,请删除g;您可能需要调整正则表达式,因为不太清楚所需的约束是什么。)

bash本身不提供使用正则表达式的replace all原语,虽然它确实有“模式”,并且如果设置了选项extglob(这是某些发行版的默认设置) ),模式足以表达模式,因此您可以使用:

echo "${variable//*( )ONCE\[*([^]])]*( )/$'\n'}"

同样,您可以通过将//更改为/来进行替换,您可能需要更改模式以满足您的确切需求。

这就留下了如何使用正则表达式指定的分隔符实际拆分bash变量的问题,对于“split”的某些定义。一个可能的定义是“使用字符串的部分作为参数调用函数”;这就是我们在这里使用的那个:

# Usage:
# call_with_split <pattern> <string> <cmd> <args>...
# Splits string according to regular expression pattern and then invokes
# cmd args string-pieces
call_with_split () { 
  if [[ $2 =~ ($1).* ]]; then
    call_with_split "$1" \
                    "${2:$((${#2} - ${#BASH_REMATCH[0]} + ${#BASH_REMATCH[1]}))}" \
                    "${@:3}" \
                    "${2:0:$((${#2} - ${#BASH_REMATCH[0]}))}"
  else
    "${@:3}" "$2"
  fi
}

示例:

$ var="substring1 substring2 ONCE[0,10s] substring3"
$ call_with_split " ONCE\[[^]]*] " "$var" printf "%s\n"
substring1 substring2
substring3

答案 1 :(得分:2)

击:

s='substring1 substring2 ONCE[0,10s] substring3'

if [[ $s =~ (.+)" ONCE["[0-9]+,[0-9]+[smhd]"] "(.+) ]]; then
    echo "${BASH_REMATCH[1]}"
    echo "${BASH_REMATCH[2]}"
else 
    echo no match
fi
substring1 substring2
substring3

答案 2 :(得分:1)

您可以使用awk。将字段分隔符指定为:

'ONCE[[]0,[^]]*[]] *'

例如,使用您的示例输入:

$ awk -F 'ONCE[[]0,[^]]*[]] *' '{for(i=1;i<=NF;i++){printf $i"\n"}}' <<< "substring1 substring2 ONCE[0,10s] substring3"
substring1 substring2 
substring3