2012-07-26 53 views
3

我已经在多个文本文件看起来像这样的数据:过滤多pcregrep匹配的sed

1 DAEJ    X   -3120041.6620  -3120042.0476  -0.3856  0.0014    
        Y    4084614.2137  4084614.6871  0.4734  0.0015    
        Z    3764026.4954  3764026.7346  0.2392  0.0014    

        HEIGHT   116.0088   116.6419  0.6332  0.0017  0.0017 8.0 
        LATITUDE  36 23 57.946407 36 23 57.940907 -0.1699  0.0013  0.0012 57.5  0.0012 62.9 
        LONGITUDE 127 22 28.131395 127 22 28.132160 0.0190  0.0012  0.0013 2.3  0.0013 

,我想通过一个过滤器来运行它,以便输出将是这样的:

DAEJ: 36 23 57.940907, 127 22 28.132160, 116.6419 

(?<site>\w\w\w\w+)<filler>\r\n\r\n<filler>(?<height>\-?\d+\.\d+)<filler>(?<heightRMS>\d+\.\d+)<filler>\r\n<filler>(?<lat>\-?\ *\d+\ +\d+\ +\d+\.\d+)<filler>(?<latRMS>\d+\.\d+)<filler>\r\n<filler>(?<lon>\-?\ *\d+\ +\d+\ +\d+\.\d+)<filler>(?<lonRMS>\d+\.\d+)<filler> 

与repacing(:

我可以grepWin使用命名捕获通过搜索做到这一点很容易不够忽略未被引用的组,我会在其他实现中使用它):

$+{site}: $+{lat}, $+{lon}, $+{height} 

但当然,以通过GUI手动执行操作为代价。我想知道是否有办法通过管道pcregrep输出到sed进行文本替换来编写脚本?我知道pcregrep -M选项匹配上面的多行正则表达式模式,并且我已经成功,直到那一点,但我坚持sed结束的问题。

+0

我知道我可以通过'\ 9'而不是命名捕获来使用'\ 1'的反向引用,但是我选择后者作为优先事项。 – alfie 2012-07-26 06:02:44

+0

在steve下面的出色答案后,我意识到我仍然需要在LATITUDE/LONGITUDE数据行中奇怪格式化的负值情况下捕获可能的减号,例如' - 6 29 27.798898'。 – alfie 2012-07-26 09:15:00

回答

3

我将使用awk来处理文本文件:

awk '$1 ~ /^[0-9]+$/ { printf "%s: ", $2 } $1 == "HEIGHT" { height = $3 } $1 == "LATITUDE" { printf "%s %s %s, ", $2, $3, $4 } $1 == "LONGITUDE" { printf "%s %s %s, %s\n", $5, $6, $7, height }' file.txt 

多条线路上爆发了可读性:

$1 ~ /^[0-9]+$/ { 
    printf "%s: ", $2 
} 

$1 == "HEIGHT" { 
    height = $3 
} 

$1 == "LATITUDE" { 
    printf "%s %s %s, ", $2, $3, $4 
} 

$1 == "LONGITUDE" { 
    printf "%s %s %s, %s\n", $5, $6, $7, height 
} 

结果:

DAEJ: 36 23 57.946407, 127 22 28.132160, 116.6419 

编辑:

将下面的代码在名为script.awk文件:

$3 == "X" { 
    printf "%s: ", $2 
} 

$1 == "HEIGHT" { 
    height = $3 
} 

$1 == "LATITUDE" { 
    if ($2 == "-" && $6 == "-") { printf "-%s %s %s, ", $7, $8, $9 } 
    else if ($2 == "-") { printf "%s %s %s, ", $6, $7, $8 } 
    else if ($5 == "-") { printf "-%s %s %s, ", $6, $7, $8 } 
    else { printf "%s %s %s, ", $5, $6, $7 } 
} 

$1 == "LONGITUDE" { 
    if ($2 == "-" && $6 == "-") { printf "-%s %s %s, %s\n", $7, $8, $9, height } 
    else if ($2 == "-") { printf "%s %s %s, %s\n", $6, $7, $8, height } 
    else if ($5 == "-") { printf "-%s %s %s, %s\n", $6, $7, $8, height } 
    else { printf "%s %s %s, %s\n", $5, $6, $7, height } 
} 

像这样运行:

awk -f script.awk file.txt 
+0

谢谢!这使我更接近解决方案,做了以下修改:'awk'$ 3 ==“X”{printf“%s:”,$ 2} $ 1 ==“HEIGHT”{height = $ 3} $ 1 ==“ LATITUDE“{printf”%s%s%s“,$ 5,$ 6,$ 7} $ 1 ==”LONGITUDE“{printf”%s%s%s,%s \ n“,$ 5,$ 6,$ 7,height} 'file.txt'现在,我需要进一步修改_that_以允许Lat/Lon的负DMS值,即'\ - ?\ * \ d + \ + \ d + \ + \ d + \。\ d +'正则表达式模式,其中可能的减号可能会或可能不会与第一个整数值相隔一个空格。 – alfie 2012-07-26 09:02:19

+0

我可以做'awk'$ 3 ==“X”{printf“%s:”,$ 2} $ 1 ==“HEIGHT”{height = $ 3} $ 1 ==“LATITUDE”{printf(($ 2 ==“ - “)?”%s%s%s%s“,$ 6,$ 7,$ 8,$ 9:”%s%s%s“,$ 5,$ 6,$ 7)} $ 1 ==”LONGITUDE“{printf ($ 2 ==“ - ”)?“%s%s%s%s,%s \ n”,$ 6,$ 7,$ 8,$ 9,height:“%s%s%s,%s \ n”, $ 5,$ 6,$ 7,height)}''首先测试是否存在减号? – alfie 2012-07-26 10:43:12

+0

@alfie,我会告诉你一个'if else'块,给我一分钟左右 – Steve 2012-07-26 11:00:30

0

这可能为你工作(GNU SED):

sed '/^DAEJ/,/^\s*LONGITUDE/!d;/HEIGHT/{s/^\s*\S*\s*\S*\s*\(\S*\).*/\1/;h};/LATITUDE/{s/^\s*\(\S*\s*\)\{4\}\(\(\S*\s*\)\{2\}\S*\).*/\2/;H};/LONGITUDE/!d;s/^\s*\(\S*\s*\)\{4\}\(\(\S*\s*\)\{2\}\S*\).*/ \2/;H;g;y/\n/,/;s/\([^,]*\),\(.*\)/DAEJ: \2, \1/' file1 file2 filen