【问题标题】:How should I properly loop over a list on a gitconfig alias?我应该如何正确遍历 gitconfig 别名上的列表?
【发布时间】:2023-03-12 20:31:02
【问题描述】:

我在 .gitconfig 上创建了一个别名:

[alias]
    test =  "!f() { \
        for l in "$@"; do \
          echo "$l"; \
        done; \
        }; f"

考虑命令:

git test "foo bar" last

我期待得到:

foo bar
last

但是,我得到了:

foo
bar
last

这是与 bash 上类似的“for”命令不同的行为。为什么会这样?我应该如何让这个命令正常工作?

【问题讨论】:

    标签: bash git shell


    【解决方案1】:

    问题在于 Git 从别名扩展中去掉了双引号。你的别名定义,缩成一行,是:

    "!f() { for l in "$@"; do echo "$l"; done; }; f"
    

    Git 去掉所有未转义的双引号(当然还有前导的!),生成:

    f() { for l in $@; do echo $l; done; }; f
    

    你想让 shell 看到:

    f() { for l in "$@"; do echo "$l"; done; }; f
    

    这意味着你必须把它交给 Git:

    "!f() { for l in \"$@\"; do echo \"$l\"; done; }; f"
    

    现在每个内部双引号都被转义了,Git 会将它们留在那里供 shell 看到。

    (如果您的脚本变得复杂,我建议不要尝试将其编写为别名。如果您在$PATH 的任何位置都有一个名为git-abc 的可执行脚本并且您运行git abc , Git 会运行你的git-abc 脚本。请注意,当Git 运行你的脚本时,Git 已经扩充了它的$PATH 以包含git-core 目录,这样你就可以使用. git-sh-setup 来获取各种有用的子程序。)

    【讨论】:

      【解决方案2】:

      在发布之前,我找到了一种方法来实现我所需要的。我将别名改写为:

      [alias]
          test =  "!f() { IFS='\n'; \
              for l in "$@"; do \
                echo "$l"; \
              done; \
              }; f"
      

      IFS 重新定义成功了。我只是不确定这是否是最好的方法。我希望能对这个主题有不同的看法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-01
        • 1970-01-01
        • 2012-02-21
        • 1970-01-01
        • 2013-03-28
        • 2019-08-19
        • 1970-01-01
        相关资源
        最近更新 更多