【问题标题】:Shell: conditional appending or copying of CSVs with header [closed]Shell:有条件地附加或复制带有标题的 CSV [关闭]
【发布时间】:2020-09-01 08:58:02
【问题描述】:

目标:

  1. 将带有标题的 CSV 从一个目录复制到另一个目录。
  2. 如果目标目录中已存在 CSV,请将其附加到现有 CSV。
  3. 不要附加 CSV 标头。

什么是行数最少的 fastet bash/shell 解决方案?

简单的解决方案:

FILE=file.csv
TARGET=path/to/file.csv
if [ -f "$TARGET" ]; then
    sed 1d $FILE >> $TARGET
else 
    cp $FILE $TARGET
fi

【问题讨论】:

  • 最快、最少的行或最少的指令?第一个通常与其他无关,最少的行比最少的指令更容易实现,但几乎没有任何帮助。无论如何,我认为您不会比当前的解决方案更快或更清洁
  • @gustavz : 您可以使用tail 复制没有标题的文件。
  • 并且任何脚本都可以通过将换行符替换为; 来实现单行,因此如果您想要单行,FILE=file.csv; TARGET=path/to/file/csv; if [ -f "$TARGET" ]; then sed 1d "$FILE" >> "$TARGET"; else cp "$FILE" "$TARGET"; fi 就可以正常工作。
  • 循环测试你的实现,然后使用time。然后看看 shell 脚本的性能差异有多大,正确的算法总是能提供最佳性能,而任何其他的语法奇思妙想都是错误巢穴。示例time sh -c 'i=10000;while i=$((i-1)); [ $i -gt 0 ]; do tail -n+2 a; done >/dev/null 2>&1'
  • tail -n+2 略快于sed 1d。但我不敢相信这对你的 shell 脚本很重要。如果性能是一个真正的问题,那么 shell 可能不是该任务的明智语言选择。我现在考虑结束您的问题,因为需要更多关注。性能和外壳是矛盾的。如果您要求 shell 脚本的性能,那么您需要回答的问题和要查看的代码设计选择比 StackOverflow 上的要多得多。

标签: bash shell csv


【解决方案1】:

你可以这样做 -

{ [[ -s "$target" ]] && sed 1d "$file" || cat "$file"; } >> "$target"

您需要将测试切换到 -s,因为如果文件不存在,>> $target 会在测试发生之前创建文件...

但不要。

最好保持原样。行数越少越好。
事实上,添加 cmets。

清晰 > 简洁。


Lea 的出色版本,完全符合 POSIX:

[ -f "$target" ]; tail -n+$(($? ? 1 : 2)) "$file" >>"$target"

这是一件美丽的事情,大声笑>;o]

【讨论】:

  • 我尝试了同样的方法但失败了;)
  • 试试这个:[ -f "$target" ] && set -- tail -n+2 || set -- cat; "$@" "$file" >>"$target" 或者[ -f "$target" ]; tail -n+$((2-$?)) "$file" >>"$target" ,或者在语义上更正确:[ -f "$target" ]; tail -n+$(($??2:1)) "$file" >>"$target"
  • 无法更正我的评论,但三元算术是 tail -n+$(($??1:2)),因为当文件存在时,$? = 0 在 shell 算术中变为 false
  • @Lea,太漂亮了,我不得不将它包含在我的答案中并感谢作者。 :)
  • 使用单方括号进行测试[ -f "$target" ],所有内容都符合 POSIX;而不是使用 Bash 的方括号 [[ test ]] 语法。
猜你喜欢
  • 2021-03-15
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
  • 2021-07-15
  • 2016-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多