我想拆分字符串,例如“substring1 substring2 ONCE[0,10s] substring3”。预期结果应为(带分隔符“ONCE[0,10s]”):
substring1 substring2
substring3
问题是分隔符中的数字是可变的,例如'ONCE[0,1s]'或'ONCE[0,3m]'或'ONCE[0,10d]'等等。
我如何在 bash 脚本中执行此操作?有什么想法吗?
谢谢
最佳答案
OP 中提供的示例(以及@GlennJackman 和@devnull 提供的两个答案)假设实际问题可能是:
In bash, how do I replace the match for a regular expression in a string with a newline.
这实际上与“使用正则表达式拆分字符串”不同,除非您添加字符串不包含任何换行符的约束。即便如此,它实际上并没有“拆分”字符串;假定其他一些进程将使用换行符来拆分结果。
一旦问题被重新表述,解决方案就没有挑战性了。您可以使用任何支持正则表达式的工具,例如 sed
:
sed 's/ *ONCE\[[^]]*] */\n/g' <<<"$variable"
(如果您只想替换第一个序列,请删除 g
;您可能需要调整正则表达式,因为不太清楚所需的约束是什么。)
bash
本身不提供使用正则表达式的 replace all
原语,尽管它确实有“模式”,并且如果选项 extglob
已设置(这是某些发行版的默认设置),模式足以表达模式,因此您可以使用:
echo "${variable//*( )ONCE\[*([^]])]*( )/$'\n'}"
同样,您可以通过将 //
更改为 /
来使替换只发生一次,并且您可能需要更改模式以满足您的精确需求。
对于“拆分”的某些定义,如何使用由正则表达式指定的定界符实际拆分 bash 变量的问题仍然悬而未决。一种可能的定义是“以字符串的各个部分作为参数调用一个函数”;这就是我们在这里使用的:
# 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
关于regex - Bash 脚本 - 使用正则表达式分隔符拆分字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23114583/