cat命令的语法和用法正确吗?

时间:2019-01-07 18:15:22

标签: bash cat

(此问题是对this评论的后续,是关于git hooks的回答)

到目前为止,我对bash的技巧太过熟练,以至于无法完全理解其言论以及如何采取相应的行动。更具体地说,建议我避免以这种方式使用bash命令cat

echo "$current_branch" $(cat "$1") > "$1"

因为操作顺序取决于特定的外壳,并且最终可能破坏传递的参数的内容,所以如果我理解正确的话,提交消息本身呢?

此外,如何“将内容保存在单独的步骤中”?

以下内容有意义吗?

tmp = "$1"
echo "$current_branch" $(cat $tmp) > "$1"

3 个答案:

答案 0 :(得分:5)

建议的问题不是关于覆盖变量或参数,而是关于同时读取和写入文件通常是一个坏主意。

例如,此命令可能看起来像只是将文件写入自身,而是将其截断:

cat myfile > myfile   # Truncates the file to size 0

但是,这不是您的特定命令中的问题。保证可以在符合POSIX的外壳中工作,因为order of operations specify重定向将在扩展后 发生:

  
      
  1. 不是变量分配或重定向的单词应予以扩展。如果扩展后还剩下任何字段,则应将第一个字段视为命令名称,其余字段将作为命令的参数。

  2.   
  3. 重定向应按照重定向中所述进行。

  4.   

双重功能,从某种意义上来说,看起来无害的修改可能会触发问题,例如您是否想对结果运行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"