有没有办法使用 shell 变量替换来替换最后一次出现的匹配项?

kjo*_*kjo 5 scripting bash wildcards replace

% x=abracadabra
% echo ${x//a/o}
obrocodobro
Run Code Online (Sandbox Code Playgroud)

哼……

有没有一种方法,以取代过去使用shell substitions模式的出现(督察,没有推出sedawkperl,等)?

Cap*_*les 7

您可以通过 shell 替换来做到这一点,只是有点棘手。您基本上可以在模式插入替换之前抓取所有内容,而不是在模式之后抓取所有内容。对于您的示例,如下所示:

    x=abracadabra
    echo "${x%a*}o${x##*a}"
Run Code Online (Sandbox Code Playgroud)

编辑:或者只是按照 Steeldriver 在评论中的建议进行操作。


ste*_*ver 7

注意:这替换了尾随事件 - 与“最后一次事件”不太一样

Bash 参考手册第 3.5.3 节 Shell 参数扩展

${parameter/pattern/string} 
Run Code Online (Sandbox Code Playgroud)

模式被扩展以产生一个模式,就像在文件名扩展中一样。参数被扩展,并且模式与其值的最长匹配被替换为字符串。如果模式以“/”开头,则模式的所有匹配项都将替换为字符串。通常只替换第一个匹配项。如果模式以“#”开头,则它必须匹配参数扩展值的开头。如果模式以 '%' 开头,则它必须匹配参数扩展值的末尾。如果 string 为空,则删除模式的匹配项,并且可以省略 / 后面的模式。如果启用 nocasematch shell 选项(请参阅 Shopt Builtin 中的 shopt 描述),则执行匹配时不考虑字母字符的大小写。如果参数是 '@' 或 '',对每个位置参数依次进行替换操作,展开即为结果列表。如果参数是一个带有'@'或'' '下标的数组变量,则对数组中的每个成员依次进行替换操作,展开后就是结果列表。

所以

$ x=abracadabra
$ echo "${x/%a/o}"
abracadabro
Run Code Online (Sandbox Code Playgroud)

  • @MrJman006,这意味着您要替换的字符(或子字符串)必须位于字符串的末尾 - 因此 `${x/%r/s}` 不会替换 ` 中的最后一个(第二个)`r`例如 x=abracadabra` (您需要将匹配扩展到字符串末尾,如 `${x/%ra/sa}`) (2认同)