字符串块格式化挑战

时间:2011-06-29 15:33:41

标签: python string shell formatting awk

我正在研究从国家地震信息中心(USGS)自动下载地震参数的方法。不幸的是,他们的格式是一堆废话,我不认为我会说服他们改变他们的格式。所以,我必须格式化他们的<pre> html块,只是为了表格形式。

但是我对字符串格式化的经验是有限的,所以我被困住了(但确定那里有人可能有解决方案)。这是一个例子:

curl --silent http://earthquake.usgs.gov/earthquakes/eqinthenews/2010/uu00002715/uu00002715_gcmt.php |\
sed -n '/<pre>/,/<\/pre>/p' |\
egrep -v '(#)|(pre>)' |\
egrep '(MW)|(ORIGIN)|(LAT)|(DEP)|(BEST DBLE)|(NP1)'

提供了我需要格式化的信息:

April 15, 2010, UTAH, MW=4.6
ORIGIN TIME:      23:59:42.8 0.4
LAT:41.72N 0.03;LON:110.86W 0.03
DEP: 12.5  1.8;TRIANG HDUR:  0.6
BEST DBLE.COUPLE:M0= 1.07*10**23
NP1: STRIKE=193;DIP=35;SLIP= -80

我想要一个像这样的格式:

name date       time       lon     lat   dep  dep_err Mw  M0      strike dip slip
UTAH 2010/04/15 23:59:42.8 -110.86 41.72 12.5 1.8     4.6 1.07e23 193    35  -80

请注意经度将转换为东经(因此符号更改)。

我希望解决方案位于awkpythonunix shell命令中,但我会接受rubyperl(我可能不会理解发生了什么。)

3 个答案:

答案 0 :(得分:3)

为什么不使用其中一种XML格式的Feed,例如this one。我确信它更容易解析。

答案 1 :(得分:2)

使用正则表达式解析html通常被认为是一个非常非常糟糕的主意,所以我第二次提出使用RSS提要的Abizern建议。事实上,USGS也提供XML下载(见http://earthquake.usgs.gov/earthquakes/catalogs/)。

如果由于某种原因你不能这样做并且 使用html,那么<pre>块没有进一步的结构(排除一些像lxml或beautifulsoup一样的好东西)然后以下python适用于此示例...正则表达式可能非常脆弱(坦率地说,cludgey)并且需要调整以处理更多示例/异常。

这写出一个excel文件,所以你应该能够在一个循环中弹出它来刮掉多个页面(玩好并检查它们的术语,限制速率和缓存)。

import httplib2
import re
from xlwt import Workbook

h = httplib2.Http(".cache")
url = 'http://earthquake.usgs.gov/earthquakes/eqinthenews/2010/uu00002715/uu00002715_gcmt.php'
resp, content = h.request(url, "GET")
regex = re.compile("<pre>\s*(?P<date>.* \d{2}, \d{4}), (?P<name>\w.*), MW=(?P<Mw>\d.\d).*ORIGIN TIME:\s*(?P<time>\d{2}:\d{2}:\d{2}.\d).*LAT:\s*(?P<lat>\d{2,3}.\d{2,3}[N|S]).*LON:\s*(?P<lon>\d{2,3}.\d{2,3}[W|E]).*DEP:\s*(?P<dep>\d{2,3}.\d)\s*(?P<dep_err>\d{1,3}.\d);.*M0=\s*(?P<M0>\d.\d{1,2}\*\d{1,2}\*\*\d{1,2}).*STRIKE=(?P<strike>\d{1,3}).*DIP=(?P<dip>\d{1,3}).*SLIP=\s*(?P<slip>[-|+]\d{1,3}).*NP2",re.MULTILINE|re.DOTALL)
r = regex.search(content)
data = r.groupdict()

headers = ['name', 'date', 'time', 'lon', 'lat', 'dep', 'dep_err', 'Mw', 'M0', 'strike', 'dip', 'slip']
wb = Workbook()
ws = wb.add_sheet('Quakes')

column = 0
for header in headers:
    ws.write(0, column, header)
    ws.write(1, column,data[header])
    column+=1
wb.save('quakes.xls')

你应该 肯定 使用XML / RSS,尽管你可以:)

答案 2 :(得分:1)

这是一个awk脚本,可以帮助你完成大部分工作。转换Lon,date,M0等作为练习:

curl --silent http://earthquake.usgs.gov/earthquakes/eqinthenews/2010/uu00002715/uu00002715_gcmt.php |
awk '
    BEGIN {
        FS = "[,:;= ]+"
        OFS = "^"
    }
    /<pre>/ {process=1}
    /<\/pre>/ {process=0}
    ! process {next}
    /MW=/ {
        date = $1 " " $2 " " $3
        place = $4
        mw = $NF
    }
    /^ORIGIN TIME:/ {
        otime = $3 ":" $4 ":" $5
    }
    /^LAT:.*LON:/ {
        lat = $2
        lon = $5
    }
    /^DEP:/ {
        dep = $2
        dep_err = $3
    }
    /^BEST DBLE.COUPLE:/ {
        m0 = $NF
    }
    /^NP1:/ {
        strike = $3
        dip = $5
        slip = $7
    }
    END {
        print "name", "date", "time", "lon", "lat", "dep", "dep_err", "Mw", "M0", "strike", "dip", "slip"
        print place, date, otime, lon, lat, dep, dep_err, mw, m0, strike, dip, slip
    }
' | column -s ^ -t

输出:

name  date           time        lon      lat     dep   dep_err  Mw   M0           strike  dip  slip
UTAH  April 15 2010  23:59:42.8  110.86W  41.72N  12.5  1.8      4.6  1.07*10**23  193     35   -80