(此问题是对this评论的后续,是关于git hooks的回答)
到目前为止,我对bash的技巧太过熟练,以至于无法完全理解其言论以及如何采取相应的行动。更具体地说,建议我避免以这种方式使用bash命令cat
:
echo "$current_branch" $(cat "$1") > "$1"
因为操作顺序取决于特定的外壳,并且最终可能破坏传递的参数的内容,所以如果我理解正确的话,提交消息本身呢?
此外,如何“将内容保存在单独的步骤中”?
以下内容有意义吗?
tmp = "$1"
echo "$current_branch" $(cat $tmp) > "$1"
答案 0 :(得分:5)
建议的问题不是关于覆盖变量或参数,而是关于同时读取和写入文件通常是一个坏主意。
例如,此命令可能看起来像只是将文件写入自身,而是将其截断:
cat myfile > myfile # Truncates the file to size 0
但是,这不是您的特定命令中的问题。保证可以在符合POSIX的外壳中工作,因为order of operations specify重定向将在扩展后 发生:
不是变量分配或重定向的单词应予以扩展。如果扩展后还剩下任何字段,则应将第一个字段视为命令名称,其余字段将作为命令的参数。
重定向应按照重定向中所述进行。
双重功能,从某种意义上来说,看起来无害的修改可能会触发问题,例如您是否想对结果运行sed
,这仍然有点脆弱。由于重定向(> "$1"
)和命令替换$(cat "$1")
现在位于单独的命令中,因此POSIX定义不再为您节省:
# Command may now randomly result in the original message being deleted
echo "$current_branch $(cat "$1")" | sed -e 's/(c)/©/g' > "$1"
类似地,如果将其重构为功能,它也会突然停止工作:
# Command will now always delete the original message
modify_message() {
echo "$current_branch $(cat "$1")"
}
modify_message "$1" > "$1"
您可以通过写入临时文件来避免这种情况,然后替换原始文件。
tmp=$(mktemp) || exit
echo "$current_branch $(cat "$1")" > "$tmp"
mv "$tmp" "$1"
答案 1 :(得分:1)
我认为,最好保存到另一个文件。
您可以尝试
echo "$current_branch" > tmp
cat "$1" >> tmp # merge these into
# echo "$current_branch" $(cat "$1") > tmp
# may both OK
mv tmp "$1"
但是我不确定我的理解是否正确,或者有更好的解决方案。
这就是我认为的核心问题。很难确定$()
块和>
的“优先级”。如果>
被“更早”执行,那么echo "$current_branch"
将重写“ $ 1”文件并删除原始内容“ $ 1”,这是灾难。如果$()
是“较早”执行的,那么一切都会按预期进行。但是,存在风险,我们应该避免这种风险。
答案 2 :(得分:1)
在这里,命令组要比替换命令好得多。请注意与Geno Chen的答案相似。
{
echo "$current_branch"
cat "$1"
} > tmp && mv tmp "$1"