如何删除下划线及其前面的字符?

3
在Bash脚本中,如何高效地执行以下操作?
var="fooo_barrrr"

什么是去除所有字符直到 '_' 以及包括它之前的最佳方法,使变量变成 "barrrr"?

1
如果你有多个“_”呢?你想保留字符串的哪一部分? - fedorqui
2个回答

8

使用参数扩展

$ var="fooo_barrrr"
$ echo ${var#*_}
barrrr

要更改变量本身,请使用var=${var#*_}

请注意,这将删除第一个_及其之前的所有内容:

$ var="fooo_barrr_r"
$ echo ${var#*_}
barrr_r

如果您想删除最后一个字符,您需要使用##
$ var="fooo_barrr_r"
$ echo ${var##*_}
r

看看一些替代方案:

使用 sed

$ sed 's/^[^_]*_//' <<< "foo_barrrr_r"
barrrr_r

使用 awk 命令:

$ awk 'gsub(/^[^_]*_/,"")1' <<< "foo_barrrr_r"
barrrr_r

使用 grep 命令:

$ grep -oP '[^_]*_\K.*' <<< "foo_barrrr_r"
barrrr_r

对于所有情况,在同一变量中存储新值,请执行var=$(command <<< "$var")


${var##*_} 可以删除到最后一个下划线。 - 123
是的!我只使用,因为我知道它只是第一个重要的。不过,我正在编辑以表明这一点。谢谢。 - fedorqui
如果你正在创建一个全面的列表,你也可以使用 expr "$var" : "[^_]*_\(.*\)" - 123

1
或者,使用 grep 命令:
echo fooo_barrrr | grep -oP '.*(?=_)'

要了解每个标志的含义,请使用 grep --help

  • -P, --perl-regexp

    PATTERN 是一个 Perl 正则表达式

  • -o, --only-matching

    仅显示与 PATTERN 匹配的行的部分内容

为避免在有两个以上部分时出现错误结果,您可以使用:

echo fooo_barrrr_xyz | grep -oP '.*?(?=_)' | head -1

1
请注意,对于 echo fooo_barrrr_ca | grep -oP '.*(?=_)' 这个命令会失败。 - fedorqui
确实。我假设OP只有两个部分。已编辑。 - Maroun
考虑到有一个 shell 内置命令,这怎么算是“高效”的呢? - This isn't my real name

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接