如何读取一天中的每小时文件并合并?

如何读取一天中的每小时文件并合并?

我有一个 Netcdf 文件的文件夹。这些文件是一个月六个小时的风文件。我想合并所有文件。我不知道如何制作一个 shell 脚本来按小时顺序读取文件以将它们组合起来。请帮忙。

anal_00z20230118.nc
anal_00z20230119.nc
anal_00z20230120.nc
anal_00z20230121.nc
anal_00z20230122.nc
anal_00z20230123.nc
anal_00z20230124.nc
anal_00z20230125.nc
anal_00z20230126.nc
anal_00z20230127.nc
anal_00z20230128.nc
anal_00z20230129.nc
anal_00z20230130.nc
anal_00z20230131.nc
anal_06z20230118.nc
anal_06z20230119.nc
anal_06z20230120.nc
anal_06z20230121.nc
anal_06z20230122.nc
anal_06z20230123.nc
anal_06z20230124.nc
anal_06z20230125.nc
anal_06z20230126.nc
anal_06z20230127.nc
anal_06z20230128.nc
anal_06z20230129.nc
anal_06z20230130.nc
anal_12z20230118.nc
anal_12z20230119.nc
anal_12z20230120.nc
anal_12z20230121.nc
anal_12z20230122.nc
anal_12z20230123.nc
anal_12z20230124.nc
anal_12z20230125.nc
anal_12z20230126.nc
anal_12z20230127.nc
anal_12z20230128.nc
anal_12z20230129.nc
anal_12z20230130.nc
anal_18z20230118.nc
anal_18z20230119.nc
anal_18z20230120.nc
anal_18z20230121.nc
anal_18z20230122.nc
anal_18z20230123.nc
anal_18z20230124.nc
anal_18z20230125.nc
anal_18z20230126.nc
anal_18z20230127.nc
anal_18z20230128.nc
anal_18z20230129.nc
anal_18z20230130.nc

答案1

使用 GNU awk 和 zsh:

set -o extendedglob
LC_ALL=C gawk '
  BEGINFILE {out = gensub(/(.*_)[0-9]{2}z/, "\\1", FILENAME) ".combined"}
  {print > out}' ./*_(00|06|12|18)z[0-9](#c8).nc

anal_20230130.nc.combined将为每组文件编写一个anal_XXz20230130.nc

在 中,您需要等效bash的 glob 模式。./*_@(00|06|12|18)z[0123456789][0123456789][0123456789][0123456789][0123456789][0123456789][0123456789][0123456789].ncshopt -s extglob failglob

在 和 中bashzshglob 都按词法顺序展开,因此*_00z*文件将出现在*_06z*文件本身之前,文件*_12z*本身出现在文件之前*_18z*

如果有大量文件,您可能会遇到execve()参数+环境大小的限制并得到一个“参数列表太长”错误。

可以通过将列表传递给 zsh 的内置函数(因此不涉及 execve() )print -rNC1来打印它并以 NUL 分隔传递给 来避免这种情况gawk

set -o extendedglob
print -rNC1 ./*_(00|06|12|18)z[0-9](#c8).nc(N) |
  LC_ALL=C gawk '
    !start {ARGV[ARGC++] = $0; next}
    BEGINFILE {out = gensub(/(.*_)[0-9]{2}z/, "\\1", FILENAME) ".combined"}
    {print > out}' RS='\0' - start=1 RS='\n'

bash没有print -rNC1,但您可以使用函数来模拟它:

print0() { [ "$#" -eq 0 ] || printf '%s\0' "$@"; }

并使用nullglob而不是来获得与 的glob 限定符failglob等效的内容。zshN

请注意,如果这些 6 小时文件在一行中间分割(例如,如果anal_00z20230130.nc以 结尾,后面unix.sta不跟换行符并anal_06z20230130.nc以 开头ckexchange.com,则组合文件将具有unix.sta<newline>ckexchange.com而不是unix.stackexchange.com,因为它将在读取的每个记录后gawk添加一个,ORS甚至是非如果这不是您想要的或者这些文件不是文本文件,您可以printprintf "%s", $0 RT.

相关内容