`cat` 命令的语法和用法正确吗?
Correct syntax and usage of `cat` command?
(这个问题是 this 评论的后续,在关于 git 钩子的回答中)
我在 bash(到目前为止)方面太不熟练,无法完全理解这句话以及如何采取相应的行动。更具体地说,有人建议我避免以这种方式使用 bash 命令 cat
:
echo "$current_branch" $(cat "") > ""
因为操作的顺序取决于特定的 shell 并且它最终可能会破坏传递的参数的内容,所以如果我做对了提交消息本身?
另外,如何"save the contents in a separate step"?
以下是否有意义?
tmp = ""
echo "$current_branch" $(cat $tmp) > ""
在我看来,最好保存到另一个文件。
你可以试试
echo "$current_branch" > tmp
cat "" >> tmp # merge these into
# echo "$current_branch" $(cat "") > tmp
# may both OK
mv tmp ""
但是我不确定我的理解是否正确,或者有更好的解决方案。
这就是我认为的核心问题。 $()
块和>
块的"precedence"很难决定。如果>
执行了"earlier",那么echo "$current_branch"
会重写“$1”文件,丢弃“$1”原来的内容,这是一场灾难.如果 $()
被执行 "earlier",那么一切都按预期工作。但是,这是有风险的,我们应该避免它。
提议的问题不是关于覆盖变量或参数,而是关于同时读取和写入文件通常不是一个好主意这一事实。
例如,此命令可能看起来只是将文件写入自身,但它 运行 对其进行分类:
cat myfile > myfile # Truncates the file to size 0
但是,这不是您的特定命令的问题。它保证在 POSIX 兼容 shell 中工作,因为 order of operations specify 重定向将发生 after 扩展:
The words that are not variable assignments or redirections shall be expanded. If any fields remain following their expansion, the first field shall be considered the command name and remaining fields are the arguments for the command.
Redirections shall be performed as described in Redirection.
Double-however,从某种意义上说,它仍然有点脆弱,看似无害的修改可能会引发问题,比如如果你想 运行 sed
在结果上。由于重定向 (> ""
) 和命令替换 $(cat "")
现在在单独的命令中,因此 POSIX 定义不再为您节省:
# Command may now randomly result in the original message being deleted
echo "$current_branch $(cat "")" | sed -e 's/(c)/©/g' > ""
同样,如果重构为一个函数,它也会突然停止工作:
# Command will now always delete the original message
modify_message() {
echo "$current_branch $(cat "")"
}
modify_message "" > ""
您可以通过写入临时文件然后替换原始文件来避免这种情况。
tmp=$(mktemp) || exit
echo "$current_branch $(cat "")" > "$tmp"
mv "$tmp" ""
命令组比这里的命令替换要好得多。请注意与 Geno Chen 的回答相似。
{
echo "$current_branch"
cat ""
} > tmp && mv tmp ""
(这个问题是 this 评论的后续,在关于 git 钩子的回答中)
我在 bash(到目前为止)方面太不熟练,无法完全理解这句话以及如何采取相应的行动。更具体地说,有人建议我避免以这种方式使用 bash 命令 cat
:
echo "$current_branch" $(cat "") > ""
因为操作的顺序取决于特定的 shell 并且它最终可能会破坏传递的参数的内容,所以如果我做对了提交消息本身?
另外,如何"save the contents in a separate step"?
以下是否有意义?
tmp = ""
echo "$current_branch" $(cat $tmp) > ""
在我看来,最好保存到另一个文件。
你可以试试
echo "$current_branch" > tmp
cat "" >> tmp # merge these into
# echo "$current_branch" $(cat "") > tmp
# may both OK
mv tmp ""
但是我不确定我的理解是否正确,或者有更好的解决方案。
这就是我认为的核心问题。 $()
块和>
块的"precedence"很难决定。如果>
执行了"earlier",那么echo "$current_branch"
会重写“$1”文件,丢弃“$1”原来的内容,这是一场灾难.如果 $()
被执行 "earlier",那么一切都按预期工作。但是,这是有风险的,我们应该避免它。
提议的问题不是关于覆盖变量或参数,而是关于同时读取和写入文件通常不是一个好主意这一事实。
例如,此命令可能看起来只是将文件写入自身,但它 运行 对其进行分类:
cat myfile > myfile # Truncates the file to size 0
但是,这不是您的特定命令的问题。它保证在 POSIX 兼容 shell 中工作,因为 order of operations specify 重定向将发生 after 扩展:
The words that are not variable assignments or redirections shall be expanded. If any fields remain following their expansion, the first field shall be considered the command name and remaining fields are the arguments for the command.
Redirections shall be performed as described in Redirection.
Double-however,从某种意义上说,它仍然有点脆弱,看似无害的修改可能会引发问题,比如如果你想 运行 sed
在结果上。由于重定向 (> ""
) 和命令替换 $(cat "")
现在在单独的命令中,因此 POSIX 定义不再为您节省:
# Command may now randomly result in the original message being deleted
echo "$current_branch $(cat "")" | sed -e 's/(c)/©/g' > ""
同样,如果重构为一个函数,它也会突然停止工作:
# Command will now always delete the original message
modify_message() {
echo "$current_branch $(cat "")"
}
modify_message "" > ""
您可以通过写入临时文件然后替换原始文件来避免这种情况。
tmp=$(mktemp) || exit
echo "$current_branch $(cat "")" > "$tmp"
mv "$tmp" ""
命令组比这里的命令替换要好得多。请注意与 Geno Chen 的回答相似。
{
echo "$current_branch"
cat ""
} > tmp && mv tmp ""