![如何读取一天中的每小时文件并合并?](https://linux22.com/image/217918/%E5%A6%82%E4%BD%95%E8%AF%BB%E5%8F%96%E4%B8%80%E5%A4%A9%E4%B8%AD%E7%9A%84%E6%AF%8F%E5%B0%8F%E6%97%B6%E6%96%87%E4%BB%B6%E5%B9%B6%E5%90%88%E5%B9%B6%EF%BC%9F.png)
我有一个 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].nc
shopt -s extglob failglob
在 和 中bash
,zsh
glob 都按词法顺序展开,因此*_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
等效的内容。zsh
N
请注意,如果这些 6 小时文件在一行中间分割(例如,如果anal_00z20230130.nc
以 结尾,后面unix.sta
不跟换行符并anal_06z20230130.nc
以 开头ckexchange.com
,则组合文件将具有unix.sta<newline>ckexchange.com
而不是unix.stackexchange.com
,因为它将在读取的每个记录后gawk
添加一个,ORS
甚至是非如果这不是您想要的或者这些文件不是文本文件,您可以print
将printf "%s", $0 RT
.