我遇到的git for-each-ref
的最高级用途涉及eval
。例如,the last example in the git-for-each-ref
man page使用eval
来执行fmt
变量的内容:
#!/bin/sh
fmt='
r=%(refname)
# ... omitted, for conciseness ...
'
eval=`git for-each-ref --shell --format="$fmt" \
# ... omitted, for conciseness ...
refs/tags`
eval "$eval"
然而,the use of eval
is associated with security risks;尽可能避免它被视为良好做法。
这是一个真实的例子,改编自this answer:
#!/bin/sh
fmt='
ref=%(refname:short)
if git merge-base --is-ancestor $1 $ref; then
printf "%s\n" "$ref"
fi
'
eval "$(git for-each-ref --shell --format="$fmt" refs/heads/)"
在此特定示例中,如何避免使用eval
?我已经查看了Zenexer's answer中列出的选项,但我找不到能够解决问题的选项。我正在寻找可移植的(跨不同的shell)解决方案。
答案 0 :(得分:3)
不要使用eval
将数据视为代码,而是让git for-each-ref
以易于处理的格式输出数据流。然后,您为该数据编写自定义处理器。
git for-each-ref --format "<values>" \
# more options
refs/tags | while read refname object_type <more args> ; do
<code>
done
至于你给出的具体例子,这里是一个等效的非eval版本:
#!/bin/bash
if [ $# -ne 1 ]; then
printf "usage: git branchesthatcontain <rev>\n\n"
exit 1
fi
rev=$1
git for-each-ref --format='%(refname:short)' refs/heads \
| while read ref; do
if git merge-base --is-ancestor "$rev" "$ref"; then
echo "$ref"
fi;
done
exit $?
我必须补充一点git-for-each-ref
确实包含--shell
,--python
和--tcl
标记,以确保数据被正确转义:这与{中的情况不同{3}}您提到的问题。
the accepted answer也很重要。