当前位置: 首页 > ai >正文

高效处理NetCDF文件经纬度转换:一个纯CDO驱动的Bash脚本详解

前言

在气候科学、海洋学和地球系统建模领域,NetCDF(Network Common Data Form)文件是存储多维科学数据的标准格式。然而,这些文件常常面临经纬度范围不一致的问题——有些数据使用[-180, 180]的地理标准范围,而另一些则采用[0, 360]的气象标准,甚至偶尔出现跨越日期变更线或特殊范围(如20.5-379.5)的异常。这不仅会干扰数据可视化和分析,还可能导致模型输入错误。作为一名从事地理信息系统和数据处理的从业者,我经常遇到这类挑战,因此开发了一个灵活的Bash脚本,利用强大的CDO(Climate Data Operators)工具来自动化处理这些问题。

这个脚本支持单文件和批量模式,能够轻松实现经度范围转换、纬度顺序反转,并自动检测特殊情况,如跨越日期变更线的数据。它还集成了并行处理、日志记录和进度显示等实用功能,帮助用户高效管理大规模数据集。在这篇博客中,我将详细介绍脚本的配置、使用方法、核心代码逻辑,以及一些实际应用案例和优化建议。无论你是科研工作者、数据分析师,还是初学者,这款脚本都能显著简化你的工作流程。让我们一起来探索如何让NetCDF数据处理变得更智能、更可靠!

脚本

#!/bin/bash# ================================================================
#                    NC文件经纬度转换脚本
#                      纯CDO版本 v3.0
# ================================================================
# 功能说明:
#   1. 支持单文件和批量处理模式
#   2. 支持经度范围转换, -180-180和0-360之间转换(包括20.5-379.5等特殊范围)
#   3. 支持纬度反转
#   4. 自动检测并处理跨越日期变更线的数据
# ================================================================# ┌──────────────────────────────────────────────────────────────┐
# │                         参数配置区                            │
# │              请根据需求修改以下参数,然后运行脚本              │
# └──────────────────────────────────────────────────────────────┘# ══════════════════════════════════════════════════════════════════════
# 1. 基本路径和模式配置
# ══════════════════════════════════════════════════════════════════════# INPUT_PATH - 输入路径(必填)| 单文件路径 | 目录路径
# 说明:要处理的NC文件路径或包含NC文件的目录路径
INPUT_PATH="test" # 替换成自己的路径# OUTPUT_PATH - 输出路径(选填)| 留空自动生成 | 指定文件/目录路径  
# 说明:留空时单文件模式生成"原名_xxx.nc",批量模式创建"输入目录_processed"
OUTPUT_PATH="test_processed" #替换成自己的路径# PROCESS_MODE - 处理模式 | auto(自动检测) | single(单文件) | batch(批量)
# 说明:auto根据INPUT_PATH自动判断,推荐使用
PROCESS_MODE="auto"# ══════════════════════════════════════════════════════════════════════
# 2. 经纬度处理配置
# ══════════════════════════════════════════════════════════════════════# PROCESS_LONGITUDE - 经度处理 | yes(启用) | no(禁用)
# 说明:是否对经度进行范围转换,处理跨日期变更线等问题
PROCESS_LONGITUDE="yes"# LONGITUDE_TARGET - 目标范围 | [-180,180](地理标准) | [0,360](气象标准)
# 说明:[-180,180]西经为负值,[0,360]所有经度为正值,会自动处理>360度的特殊范围
LONGITUDE_TARGET="[0,360]" #"[-180,180]"# LONGITUDE_METHOD - 处理方法 | auto(自动) | sellonlatbox | shiftlon | expr  
# 说明:auto自动选择最佳方法,expr适合特殊范围(如20.5-379.5)
LONGITUDE_METHOD="auto"# SPECIAL_LON_HANDLING - 特殊经度处理(>360度) | yes(启用) | no(禁用)
# 说明:自动检测并处理超过360度的经度范围
SPECIAL_LON_HANDLING="yes"# PROCESS_LATITUDE - 纬度处理(反转顺序) | yes(启用) | no(禁用) 
# 说明:反转纬度顺序(北→南 ↔ 南→北),用于某些模型输出格式转换
PROCESS_LATITUDE="yes"# ══════════════════════════════════════════════════════════════════════
# 3. 文件处理选项  
# ══════════════════════════════════════════════════════════════════════# FILE_SUFFIX - 输出文件后缀 | 任意字符串
# 说明:自定义后缀,会自动添加处理类型标识(如_lon-180-180)
FILE_SUFFIX="processed"# OVERWRITE_EXISTING - 覆盖已存在文件 | yes(覆盖) | no(跳过) | backup(备份后覆盖)
# 说明:backup会创建.bak备份文件
OVERWRITE_EXISTING="no"# SKIP_PATTERN - 跳过文件模式 | 留空不跳过 | *test* | *_processed* 等通配符
# 说明:批量处理时跳过匹配此模式的文件,支持*?[]通配符
SKIP_PATTERN="*_processed*"# CHECK_OUTPUT - 检查输出文件完整性 | yes(检查) | no(不检查)
# 说明:处理后验证输出文件是否正确生成且可读
CHECK_OUTPUT="yes"# KEEP_TEMP_FILES - 保留临时文件(调试用) | yes(保留) | no(删除)
# 说明:调试时可保留中间文件,正常使用建议删除
KEEP_TEMP_FILES="no"# ══════════════════════════════════════════════════════════════════════
# 4. 性能和日志配置
# ══════════════════════════════════════════════════════════════════════# PARALLEL_PROCESSING - 并行处理(需GNU parallel) | yes(启用) | no(串行)
# 说明:批量模式下同时处理多个文件,需要先安装parallel工具
PARALLEL_PROCESSING="yes"# MAX_PARALLEL_JOBS - 最大并行数 | auto(自动) | 4 | 8 | 16 等正整数
# 说明:建议设为CPU核心数的50-75%,auto根据CPU自动决定, 但是使用auto的时候会报错。
MAX_PARALLEL_JOBS="4"# CDO_OPTIONS - CDO选项 | -s(静默) | -v(详细) | -O(覆盖) | -z zip_9(压缩)
# 说明:可组合使用,如"-s -z zip_6"表示静默+压缩
CDO_OPTIONS="-v"# LOG_LEVEL - 日志级别 | ERROR | WARN | INFO(推荐) | DEBUG
# 说明:INFO显示主要处理信息,DEBUG显示详细调试信息
LOG_LEVEL="INFO"# LOG_FILE - 日志文件 | auto(自动生成) | 指定路径 | 留空禁用
# 说明:auto生成带时间戳的日志文件,留空则不保存日志
LOG_FILE="auto"# SHOW_PROGRESS - 显示进度 | yes(显示) | no(不显示)
# 说明:批量处理时显示进度条和百分比
SHOW_PROGRESS="yes"# DRY_RUN - 演练模式(仅显示操作) | yes(演练) | no(正常执行)
# 说明:演练模式只显示将要执行的操作,不实际处理文件
DRY_RUN="no"# ┌──────────────────────────────────────────────────────────────┐
# │                    参数配置结束                              │
# │                  以下为脚本执行代码                          │
# │                    请勿修改!                                │
# └──────────────────────────────────────────────────────────────┘# ================================================================
#                         脚本执行部分
# ================================================================# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m'# 全局变量
SCRIPT_NAME=$(basename "$0")
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
START_TIME=$(date +%s)
PROCESSED_COUNT=0
FAILED_COUNT=0
SKIPPED_COUNT=0# 生成日志文件名
if [ "$LOG_FILE" = "auto" ]; then# 尝试在当前目录创建日志文件,如果失败则使用临时目录LOG_FILE="nc_process_$(date +%Y%m%d_%H%M%S).log"if ! touch "$LOG_FILE" 2>/dev/null; thenLOG_FILE="/tmp/nc_process_$(date +%Y%m%d_%H%M%S).log"if ! touch "$LOG_FILE" 2>/dev/null; thenLOG_FILE="/dev/null"echo "警告: 无法创建日志文件,日志将被禁用"fifi
elif [ -z "$LOG_FILE" ]; thenLOG_FILE="/dev/null"
fi# ========================
# 日志函数
# ========================
log() {local level=$1shiftlocal message="$*"local timestamp=$(date '+%Y-%m-%d %H:%M:%S')case $level inERROR)[ "$LOG_LEVEL" != "NONE" ] && echo -e "${RED}[ERROR]${NC} $message" >&2[ "$LOG_FILE" != "/dev/null" ] && echo "[$timestamp] [ERROR] $message" >> "$LOG_FILE" 2>/dev/null;;WARN)if [[ "$LOG_LEVEL" =~ ^(WARN|INFO|DEBUG)$ ]]; thenecho -e "${YELLOW}[WARN]${NC} $message"fi[ "$LOG_FILE" != "/dev/null" ] && echo "[$timestamp] [WARN] $message" >> "$LOG_FILE" 2>/dev/null;;INFO)if [[ "$LOG_LEVEL" =~ ^(INFO|DEBUG)$ ]]; thenecho -e "${GREEN}[INFO]${NC} $message"fi[ "$LOG_FILE" != "/dev/null" ] && echo "[$timestamp] [INFO] $message" >> "$LOG_FILE" 2>/dev/null;;DEBUG)if [ "$LOG_LEVEL" = "DEBUG" ]; thenecho -e "${CYAN}[DEBUG]${NC} $message"fi[ "$LOG_FILE" != "/dev/null" ] && echo "[$timestamp] [DEBUG] $message" >> "$LOG_FILE" 2>/dev/null;;*)echo "$message"[ "$LOG_FILE" != "/dev/null" ] && echo "[$timestamp] $message" >> 
http://www.xdnf.cn/news/18303.html

相关文章:

  • [大模型微调]基于llama_factory用 LoRA 高效微调 Qwen3 医疗大模型:从原理到实现
  • WPF中UI线程频繁操作造成卡顿的处理
  • 中文房间悖论:人工智能理解力的哲学拷问
  • 深度解析游戏引擎中的相机:视图矩阵
  • 小体积晶振1610/2016/3225选型参数
  • 小游戏AssetBundle加密方案解析
  • 5.Shell脚本修炼手册---Linux正则表达式(Shell三剑客准备启动阶段)
  • 电能质量监测装置 分布式光伏安全并网“准入证”
  • 8.21 随机森林
  • conda create 报错:Unable to read repodata JSON(镜像 pkgs/free 导致)
  • Neovim clangd LSP 配置出现 “attempt to call field ‘ge‘”
  • C# 13 与 .NET 9 跨平台开发实战(第一章:开发环境搭建与.NET概述-下篇)
  • 鸿蒙中基础耗时分析:Time分析
  • 音视频面试题集锦第 29 期
  • JetBrains Mono字体
  • Vue3组件系统完全指南:从入门到面试通关
  • (第二十期下)超链接的更多分类
  • 血缘元数据采集开放标准:OpenLineage Dataset Facets
  • java开发面试题(提高篇)
  • 大数据毕业设计选题推荐-基于大数据的北京气象站数据可视化分析系统-Hadoop-Spark-数据可视化-BigData
  • JavaScript基础语法five
  • Python学习 -- MySQL数据库的查询及案例
  • 计算两幅图像在特定交点位置的置信度评分。置信度评分反映了该位置特征匹配的可靠性,通常用于图像处理任务(如特征匹配、立体视觉等)
  • redis-缓存-双写一致性
  • git 常用命令整理
  • 【倍增 桶排序】后缀数组
  • 【Java后端】Spring Boot 全局异常处理最佳实践
  • Firefox 142 引入 CRLite 用于私有证书撤销
  • LeetCode热题100--101. 对称二叉树--简单
  • 【clion】visual studio的sln转cmakelist并使用clion构建32位