给出一个字符串,如
string="val1 val2 val3 val4"
如何使用bash substring replacement来删除给定的子字符串及其相邻的空格(可能存在也可能不存在)?
例如,这会产生额外的空格:
val='val2'
string=${string/$val/}
# string = "val1 val3 val4"
在我的现实代码中,我事先不知道子字符串是什么或它在字符串中的位置,所以如果它具有前导或尾随空格将是未知的。我想做这样的事情,就像你在sed
中所做的那样,但当然它没有工作:
val=" *val2 *"
string=${string/$val/ }
# In my fictitious universe, string = "val1 val3 val4"
# In the real world, string = "val1"
在sed
中,我会使用sed -e 's/ *val2 */ /'
之类的内容,但我想在bash中完成所有这些操作。
有没有办法定义子字符串,使得模式包含零个或多个空格+' val2' +零或多个空格?
答案 0 :(得分:3)
已启用extglob
shell选项,
$ string="val1 val2 val3 val4"
$ v=val2
$ echo "${string/*( )$v*( )/ }"
val1 val3 val4
string/
用于搜索和替换第一次出现的模式。使用string//
替换所有匹配项。有关详细信息,请参阅https://regex101.com/r/hS2dI4/2 *( )
表示零个或多个空格。有关extglob
选项答案 1 :(得分:3)
考虑作为初始状态:
v=val2
string="val1 val21 val2 val3 val4"
实现此问题所要求的准确行为将导致:
string="val1 1 val3 val4"
......或者,或许:
string="val1 1 val2 val3 val4"
我在下面假设你真正想要输出的内容是:
string="val1 val21 val3 val4"
这比完全必要的更多参与(我将使用下面显示的替代方法用于手头的直接案例),但显示在本机bash中使用正则表达式替换字符串 - 这通常是有用的技术的
考虑使用[[ $string =~ $re ]]
,它使用正则表达式BASH_REMATCH
中的任何组填充数组re
:
string="val1 val2 val3 val4"
val=val2
if [[ $string =~ (.*(^|[[:space:]]))"$val"(($|[[:space:]]).*) ]]; then
string="${BASH_REMATCH[1]}${BASH_REMATCH[3]}"
string=${string// / } # deal with any places where spaces are doubled up
fi
无条件地在字符串前面加上空格和后缀意味着你可以使用相同的替换逻辑,没有类似正则表达式的条件,你的值将被删除位于字符串中的任何位置:
string="val1 val2 val3 val4"
val=val2
s=" $string " # Unconditionally add leading and trailing spaces
s=${s// $val / } # Substitute the value only when surrounded by space
s=${s# }; s=${s% } # Trim leading and trailing spaces back off
string=$s