如何在git配置别名内的bash片段内的命令替换内使用括号字符?

Ste*_* Lu 2 git bash

这是我正在编辑的配置的摘录。这是在[alias]my的部分内.gitconfig

ignored = !git ls-files -v | grep "^S"
status-with-ignored = "!f() { git status; ignored=$(git ignored | cut -d ' ' -f 2 | sed -e s/^/z/ -e s/$/z/); [ -n \"$ignored\" ] && echo \"git skip-worktree (ignored):\n$ignored\"; };f"
Run Code Online (Sandbox Code Playgroud)

我基本上是在尝试将 的输出着色,git ignored因为我将其粘贴到 git status 的末尾。我上面显示的工作正常,但fatal: bad config file line 18 in ~/.gitconfig如果我的sed命令中有任何括号(这对于构建正则表达式非常有用),则它不起作用 ( )。

例如,我希望能够写一些带有括号的东西,例如sed s/^(.*)$/z\1z/代替sed -e s/^/z/ -e s/$/z/.

因为我上色的东西,我实际上是使用\x1b[31m\x1b[m等等,但你的想法。

我试过一、二、三和四个反斜杠来逃避这些括号,但没有任何效果。

Jef*_*ica 6

这里有不同的问题:一个是你的配置转义,一个sed<(date)在 .

配置转义

首先,问题bad config file不是命令替换,而是你的换行符。

[YOURS] status-with-ignored = "!f() { git status; ignored=$(git ignored | cut -d ' ' -f 2 | sed -e s/^/z/ -e s/$/z/); [ -n \"$ignored\" ] && echo \"git skip-worktree (ignored):\n$ignored\"; };f"
 [MINE] status-with-ignored = "!f() { git status; ignored=$(git ignored | cut -d ' ' -f 2 | sed -e s/^/z/ -e s/$/z/); [ -n \"$ignored\" ] && echo \"git skip-worktree (ignored):\\n$ignored\"; };f"
Run Code Online (Sandbox Code Playgroud)

看起来您\n被解释为适用于配置文件;这是需要转义的部分,而不是任何与 paren 相关的内容。

我通过让bashgit config处理我的转义,然后用 cut" "代替' '

git config alias.status-with-ignored '!f() { git status; ignored=$(git ignored | cut -d " " -f 2 | sed -e s/^/z/ -e s/$/z/); [ -n "$ignored" ] && echo "git skip-worktree (ignored):\n$ignored"; };f'
Run Code Online (Sandbox Code Playgroud)

(如果你要弄巧约逃逸单引号bash单引号,你可以,但对我来说,工作积极反对可读性。)

sed 中的括号

其次,Bash 和其他 shell 无法处理未加引号的括号。这不是特定于 git 别名的,这只是解析规则。

echo I am (Batman)    # Doesn't work
echo I am Batman      # Does work
Run Code Online (Sandbox Code Playgroud)

后者有效;蝙蝠侠没有父母。

您可以转义括号或引用字符串:

echo "I am (Batman)"  # Works
echo I am \(Batman\)  # Also works
Run Code Online (Sandbox Code Playgroud)

这使您的配置文件如下所示:

status-with-ignored = "!f() { git status; ignored=$(git ignored | cut -d ' ' -f 2 | sed -e \"s/^(.*)$/z\1z/\"); [ -n \"$ignored\" ] && echo \"git skip-worktree (ignored):\\n$ignored\"; };f"
Run Code Online (Sandbox Code Playgroud)

或者你的git config声明是这样的:

git config alias.status-with-ignored '!f() { git status; ignored=$(git ignored | cut -d " " -f 2 | sed -e "s/^(.*)$/z\1z/"); [ -n "$ignored" ] && echo "git skip-worktree (ignored):\n$ignored"; };
Run Code Online (Sandbox Code Playgroud)

git 中的进程替换

最后,似乎git alias只是不处理进程替换。从git config手册页

参数由空格分隔,支持通常的 shell 引用和转义。可以使用引号对或反斜杠来引用它们。

看起来 git 正在使用sh或它自己的解析,而不是调用bash自己,因此本机不支持非便携式 bash 扩展进程替换。你可以掏出bash:

git config alias.sample '!cat <(seq 3)'; git sample
git config alias.sample '!bash -c "cat <(seq 3)"'; git sample
Run Code Online (Sandbox Code Playgroud)

...但此时您不妨制作一个名为的脚本git-status-with-ignored并将其添加到您的路径中