You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本egrep提取METAR能见度值异常,输出0而非1SM中的1

问题分析与修正方案

原语句的核心问题

你当前用于提取能见度的命令:

visib=$( egrep -o '\s[0-9]{2}\s' metar.txt | cut -c2-3)

存在两个致命问题:

  1. 正则表达式\s[0-9]{2}\s要求匹配两位数字且前后必须有空格,但目标能见度是1SM(一位数字+后缀SM),完全不符合该模式,因此根本匹配不到目标内容。
  2. 由于匹配失败,visib变量为空,printf "%d"格式化空变量时会默认输出0,这就是你看到结果的原因。

修正后的提取命令

以下几种方案都可以正确提取1SM中的数字1:

方案1:基础正则+文本处理

visib=$(egrep -o '\s[0-9]+SM' metar.txt | cut -c2- | sed 's/SM$//')
  • \s[0-9]+SM:匹配带前置空格、后跟1个或多个数字+SM的内容(如 1SM)
  • cut -c2-:去掉开头的空格,得到1SM
  • sed 's/SM$//':移除末尾的SM,保留纯数字

方案2:Perl兼容正则直接捕获

如果你的系统支持grep -P(大部分Linux发行版默认支持),可以用更简洁的方式:

visib=$(grep -Po '\s\K[0-9]+(?=SM)' metar.txt)
  • \s\K:匹配空格后丢弃该空格,不包含在结果中
  • [0-9]+(?=SM):匹配后面紧跟SM的数字,(?=SM)是正向预查,不会把SM包含在结果里

方案3:扩展正则反向引用

visib=$(egrep -oE '\s([0-9]+)SM' metar.txt | awk '{print $2}' | sed 's/SM//')
  • -E:启用扩展正则,支持分组捕获
  • ([0-9]+):捕获数字部分,后续通过文本处理提取

脚本优化建议

你当前的脚本多次调用egrep重复读取同一个文件,效率较低。可以先将整个METAR内容读入变量,再通过字符串处理或单次匹配提取所有字段,示例如下:

#!/bin/bash
# 一次性读取METAR内容到变量
metar=$(cat metar.txt)

# 提取报告类型
report_type=$(echo "$metar" | egrep -o 'METAR|SPECI')
printf "Report type: %s\n" "$report_type"

# 提取位置代码
location=$(echo "$metar" | egrep -o 'K[A-Z]{3}')
printf "Location: %s\n" "$location"

# 提取日期时间
dt=$(echo "$metar" | egrep -o '[0-9]{6}Z')
day=${dt:0:2}
hour=${dt:2:2}
minute=${dt:4:2}
printf "Day of the month: %d\n" "$day"
printf "Time: %d:%d Zulu\n" "$hour" "$minute"

# 提取风信息
wind_info=$(echo "$metar" | egrep -o '[0-9]{5}(G[0-9]{2})?KT')
windDir=${wind_info:0:3}
windSpd=${wind_info:3:2}
printf "Winds are from %d degrees at %d Knots" "$windDir" "$windSpd"

# 处理阵风
if [[ "$wind_info" == *G* ]]; then
    gustSpd=$(echo "$wind_info" | egrep -o 'G[0-9]{2}' | cut -c2-)
    printf "\nWinds are gusting at %d Knots" "$gustSpd"
fi

# 处理风向变化
if [[ "$metar" == *V* ]]; then
    var_winds=$(echo "$metar" | egrep -o '[0-9]{3}V[0-9]{3}')
    dir1=${var_winds:0:3}
    dir2=${var_winds:4:3}
    printf "\nWinds are variable from %s degrees to %s degrees" "$dir1" "$dir2"
fi

# 提取能见度(用方案2的简洁写法)
visib=$(grep -Po '\s\K[0-9]+(?=SM)' <<< "$metar")
printf "\nVisibility: %d Statute Miles\n" "$visib"

内容的提问来源于stack exchange,提问作者FHForce99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 15:18:13