Bash - 是否可以使用 ${##} 从命令结果中删除子字符串?

Bash - 是否可以使用 ${##} 从命令结果中删除子字符串?

我想这会给我 git 中当前分支的名称。

echo "${`git symbolic-ref HEAD`##refs/heads}"

然而,这会导致

-bash: ${`git symbolic-ref HEAD`##refs/heads}: bad substitution

是否可以在单行命令结果上使用 ## 而不将结果存储在中间变量中,或者我是否必须使用其他方法,例如sed

答案1

不可以bash,但你可以zsh

printf '%s\n' "${$(git symbolic-ref HEAD)#refs/heads}"

会在那里工作。

或者你总是可以用以下方法进行剥离sed

printf '%s\n' "$(git symbolic-ref HEAD | sed '1s|^refs/heads||')"

如果要删除的部分包含换行符,情况会变得更加复杂。例如,如果要剥离的部分是$'1\n2\n3\n',您需要类似以下内容:

cmd1 -- "$(cmd2 | sed '1{$!N;$!N;$!N; s/^1\n2\n3\n//;}')"

因此,您不妨使用一个临时变量,它也有保留cmd2退出状态的好处:

strip=$'1\n2\n3\n'

out=$(cmd2); cmd2_status=$?
cmd1 -- "${out#"$strip"}"

答案2

不,恐怕这是不可能的,因为这个##习语属于多变的仅扩展,因此您始终必须引用现有变量。

但是,对于您的情况,您可能会喜欢以下技巧:

sh -c 'echo "${*##refs/heads}"' - "`git symbolic-ref HEAD`"

或者: (作为更好的巴什主义

sh -c 'echo "${*##refs/heads}"' -- "$(git symbolic-ref HEAD)"

这将运行一个非交互式的命令sh,并将命令的输出git 作为其参数,然后在该参数上使用##惯用语。

如果您可以相信命令的输出已被充分清理(即不包含*或其他通配符),您可以省去自己键入双引号。

相关内容