首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >相似字符串,不同结果

相似字符串,不同结果
EN

Stack Overflow用户
提问于 2016-02-22 00:21:53
回答 3查看 102关注 0票数 1

我正在创建一个Bash脚本来解析网页上的空气污染水平:http://aqicn.org/city/beijing/m/

文件中有很多内容,但这是相关的部分:

“iaqi”:[{“p”:“"v":59,21,112,”,pm25“I”:“北京pm25”(细颗粒物),由美国驻北京大使馆空气质量监测仪(\u7f8e\u56fd\u9a7b\u5317\u4eac\u5927\u4f7f\u9986\u7a7a\u6c14\u8d28\u91cf\u76d1\u6d4b).测量。值由0 00b5g/m3换算成空气质量指数。“},{"p":" pm10 ","v":15,5,69,”I“:”北京空气可吸入颗粒物“,北京环境保护监测中心测量。

我希望脚本解析和显示两个数字:当前的PM2.5和PM10级别(上段中的粗体中的数字)。

代码语言:javascript
复制
CITY="beijing"
AQIDATA=$(wget -q 0 http://aqicn.org/city/$CITY/m/ -O -)

PM25=$(awk -v FS="(\"p\":\"pm25\",\"v\":\\\[|,[0-9]+)" '{print $2}' <<< $AQIDATA)
PM100=$(awk -v FS="(\"p\":\"pm10\",\"v\":\\\[|,[0-9]+)" '{print $2}' <<< $AQIDATA)

echo $PM25 $PM100

即使我可以正确地显示PM2.5级别,也不能显示PM10级别。我不明白为什么,因为字符串是相似的。

有谁能解释清楚吗?

EN

回答 3

Stack Overflow用户

发布于 2016-02-22 03:28:28

以下方法基于两个步骤:

(1)提取相关JSON;

(2)使用JSON感知工具--这里是jq --从JSON中提取相关信息。

(1)理想情况下,web服务将提供允许直接获取JSON的JSON,但由于您的URL是用于使用浏览器查看的,因此需要某种形式的屏幕抓取。这种方法存在一定程度的脆性,所以这里我只提供一些目前起作用的东西:

代码语言:javascript
复制
wget -O - http://aqicn.org/city/beijing/m |
  gawk 'BEGIN{RS="function"}
         $1 ~/getAqiModel/ {
         sub(/.*var model=/,"");
         sub(/;return model;}/,"");
         print}'

(可以使用gawk或支持多字符RS的awk;如果您有另一个awk,则首先使用"function",例如:

sed $s/function/\\n/g‘#3反斜杠)

上面的输出可以管道到下面的jq命令,该命令执行上文(2)中所设想的筛选。

(2)

代码语言:javascript
复制
jq -c '.iaqi | .[]
| select(.p? =="pm25" or .p? =="pm10") | [.p, .v[0]]'

结果:

代码语言:javascript
复制
["pm25",59]
["pm10",15]
票数 3
EN

Stack Overflow用户

发布于 2016-02-22 03:16:35

我认为您的问题是,您有一个单行HTML文件,其中包含一个包含变量的脚本,该变量包含您要查找的数据。

您的字段分隔符是"p":"pm100", "v":[、逗号和一些数字。

对于pm25来说,这是可行的,因为它是第一个,并且在它之前没有发生,21或类似的事情。

然而,对于pm10,有一些是与pm25相关的。因此,第二个字段包含,21,112之间的空字符串。

@karakfa的黑客攻击似乎奏效了--但他并没有很好地解释为什么会起作用。

他所做的就是使用awk的记录分隔符(通常是换行符),并将其设置为:,[中的任何一个。因此,在您的示例中,其中一个记录将是"pm25",因为它前面有一个冒号,它是分隔符,后面是一个逗号,也是一个分隔符。

一旦它命中匹配的内容("pm25"),它将一个计数器设置为4。然后,对于这个记录和下一个记录,它会对此计数器进行计数。"pm25"本身,"v":[之间的空字符串,当用要输出的数字命中记录时,最终到达一个字符串:4 && ! 3为false,3 && ! 2为false,2 && ! 1为false,但1 && ! 0为真。由于没有执行块,awk只是打印这个记录,这是您想要的值。

更健壮的工作可能是使用xpath查找脚本,然后使用一些json解析器或类似的方法来获得值。

票数 2
EN

Stack Overflow用户

发布于 2016-02-22 01:30:32

awk去营救!

如果有必要,您可以使用这种使用手工分隔符的智能计数器的方式。设置RS,而不是FS,会在字段中循环传输,以使其自身具有awk特性。多字符RS并不适用于所有的awk (gawk支持它)。

代码语言:javascript
复制
$ awk -v RS='[:,[]' '$0=="\"pm25\""{c=4} c&&!--c' file                 
59

$ awk -v RS='[:,[]' '$0=="\"pm10\""{c=4} c&&!--c' file   
15
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35543915

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档