可以用bash子串替换使用正则表达式吗?

时间:2016-08-17 01:07:19

标签: bash shell variable-expansion parameter-expansion

给出一个字符串,如

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' +零或多个空格?

2 个答案:

答案 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选项
  • 的更多详细信息和使用,请参阅Parameter Expansion
  • 替换模式是单个空格字符

答案 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"

方法:Posix扩展正则表达式/ BASH_REMATCH

这比完全必要的更多参与(我将使用下面显示的替代方法用于手头的直接案例),但显示在本机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