bash子字符串替换可以使用regexs吗?

bash子字符串替换可以使用regexs吗?,bash,shell,variable-expansion,parameter-expansion,Bash,Shell,Variable Expansion,Parameter Expansion,给定一个字符串,例如 string="val1 val2 val3 val4" 如何使用bash子字符串替换来删除给定的子字符串及其可能存在或不存在的相邻空间 例如,这会产生额外的空间: val='val2' string=${string/$val/} # string = "val1 val3 val4" 在我的实际代码中,我事先不知道子字符串是什么,也不知道它在字符串中的位置,因此不知道它是否有前导空格或尾随空格。我想做这样的事情,就像你在sed中做的那样,但当然没有成功: val=

给定一个字符串,例如

string="val1 val2 val3 val4"
如何使用bash子字符串替换来删除给定的子字符串及其可能存在或不存在的相邻空间

例如,这会产生额外的空间:

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

如果启用了extglob shell选项

$ string="val1 val2 val3 val4"
$ v=val2
$ echo "${string/*( )$v*( )/ }"
val1 val3 val4
字符串/用于搜索和替换第一次出现的模式。使用字符串//替换所有引用。请参阅以获取进一步阅读 *表示零个或多个空格。有关extglob选项的更多详细信息和用法,请参阅 替换模式是单个空格字符 如果启用了extglob shell选项

$ string="val1 val2 val3 val4"
$ v=val2
$ echo "${string/*( )$v*( )/ }"
val1 val3 val4
字符串/用于搜索和替换第一次出现的模式。使用字符串//替换所有引用。请参阅以获取进一步阅读 *表示零个或多个空格。有关extglob选项的更多详细信息和用法,请参阅 替换模式是单个空格字符 规范问题 作为初始状态考虑:

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_重新匹配 这比严格意义上的必要性要复杂得多,我将使用下面所示的另一种方法来处理眼前的情况,但显示了在本机bash中使用正则表达式替换字符串,这通常是一种有用的技术

考虑使用[[$string=~$re]],它使用正则表达式re中的任何组填充数组BASH\u REMATCH:

用临时填充物替换图案 无条件地在字符串前面加上空格和后缀意味着您可以使用相同的替换逻辑,不带类似正则表达式的条件,并在字符串中的任何位置删除您的值:

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
规范问题 作为初始状态考虑:

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_重新匹配 这比严格意义上的必要性要复杂得多,我将使用下面所示的另一种方法来处理眼前的情况,但显示了在本机bash中使用正则表达式替换字符串,这通常是一种有用的技术

考虑使用[[$string=~$re]],它使用正则表达式re中的任何组填充数组BASH\u REMATCH:

用临时填充物替换图案 无条件地在字符串前面加上空格和后缀意味着您可以使用相同的替换逻辑,不带类似正则表达式的条件,并在字符串中的任何位置删除您的值:

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

零个或多个空格+‘val2’+零个或多个空格几乎肯定不是你想要的,因为val21会匹配这一点——毕竟两边都是零空格!我假设您真正感兴趣的是空格或start+‘val2’+空格或end……而且,一般来说,在bash中使用分隔字符串表示项目列表是错误的。例如,如果您使用的是由单个值(适用于无序列表)键控的关联数组,则从该数组中删除一个值将与未设置的arr[val2]一样简单;对于有序列表,您可以通过索引执行相同的操作。在bash中使用字符串来维护列表本身就是一种代码味道,因为它通常表示数据结构的选择不当。你说得对,我没有想到会有类似的项存在,但有不同的开头或结尾。在我的例子中,这些值以大空格分隔字符串的形式提供给我,并表示IBM i编译参数,例如TGTRLSV7R1M0 DBGVIEW*所有DFTACTGRP*否。它们总是以一些字母开头,然后是左括号,然后是一些可能以星号开头的值,然后是右括号。我使用此脚本的目标是删除与一组默认参数匹配的参数,以便剩下的参数不在我们的默认值范围内。零或多个空格+“val2”+零或多个空格几乎肯定不是您想要的,因为val21将匹配此参数-毕竟,两边都是零空格!我假设您真正感兴趣的是空格或start+‘val2’+空格或end……而且,一般来说,在bash中使用分隔字符串表示项目列表是错误的。如果您使用的是由单个值键控的关联数组[适用于unord
例如,从列表中删除一个值就像未设置的arr[val2]一样简单;对于有序列表,您可以通过索引执行相同的操作。在bash中使用字符串来维护列表本身就是一种代码味道,因为它通常表示数据结构的选择不当。你说得对,我没有想到会有类似的项存在,但有不同的开头或结尾。在我的例子中,这些值以大空格分隔字符串的形式提供给我,并表示IBM i编译参数,例如TGTRLSV7R1M0 DBGVIEW*所有DFTACTGRP*否。它们总是以一些字母开头,然后是左括号,然后是一些可能以星号开头的值,然后是右括号。我使用此脚本的目标是删除与一组默认参数匹配的参数,以便剩下的参数不在我们的默认值范围内。这符合OP的要求,但我不确定这是否是他们真正需要的。例如,这里的val21与v=val2匹配。这符合OP的要求,但我不确定这是否是他们真正需要的。例如,这里的val21将与v=val2匹配。