在空行中重复数据,直到出现非空行

时间:2012-05-23 15:10:57

标签: python awk formatting

我有一个如下所示的数据文件:

 xyz123            2.000    -0.3974     0.0  hij123       
                                          6.0  lmn123      
                                          8.7  efg123      
                                         13.9  uvw123      
                                         28.5  rst123       
 abc123            10.000     0.1943     0.0  wxy123       
                                         10.7  xyz123       
                                         19.9  pqr123     
                                         20.6  stu123      
                                         20.6  klm123      
 def123            50.000    -0.2595    19.2  jkl123      
                                         26.1  stu123      
                                         27.1  def123     
                                         27.1  ghi123     
                                         27.6  abc123

* uvw123 15.000 -0.3635

 lmn123            40.000    -0.3695     19.2  jkl123      
                                         26.1  stu123      
                                         27.1  def123     
                                         27.1  ghi123     
                                         27.6  abc123

我需要将其转换为:

xyz123,2.000,-0.3974,0.0,hij123       
xyz123,2.000,-0.3974,6.0,lmn123      
xyz123,2.000,-0.3974,8.7,efg123      
xyz123,2.000,-0.3974,13.9,uvw123      
xyz123,2.000,-0.3974,28.5,rst123       
abc123,10.000,0.1943,0.0,wxy123       
abc123,10.000,0.1943,10.7,xyz123       
abc123,10.000,0.1943,19.9,pqr123     
abc123,10.000,0.1943,20.6,stu123      
abc123,10.000,0.1943,20.6,klm123      
def123,50.000,-0.2595,19.2,jkl123      
def123,50.000,-0.2595,26.1,stu123      
def123,50.000,-0.2595,27.1,def123     
def123,50.000,-0.2595,27.1,ghi123     
def123,50.000,-0.2595,27.6,abc123

* uvw123,15.000,-0.3635,

lmn123,40.000,-0.3695,19.2,jkl123      
lmn123,40.000,-0.3695,26.1,stu123      
lmn123,40.000,-0.3695,27.1,def123     
lmn123,40.000,-0.3695,27.1,ghi123     
lmn123,40.000,-0.3695,27.6,abc123

如何使用Python或AWK或sed执行此操作?

更新:所以如果你注意到输入数据中有一行看起来像“uvw123 15.000 -0.3635”,当我使用aix的python代码时,这一行就搞砸了。有没有办法修改代码并正确输出行,例如我展示的行?

8 个答案:

答案 0 :(得分:1)

这是一个Python解决方案:

import re

with open('data.txt') as f:
  prev = []
  for line in f:
    tok = [t for t in re.split(r'\s+', line.rstrip()) if t]
    if len(tok) < len(prev):
      tok = prev[:-len(tok)] + tok
    print ','.join(tok)
    prev = tok

它会跟踪每列的最新值(在prev中)并使用它来填充当前行中缺少的列。

答案 1 :(得分:1)

awk 'BEGIN {OFS = ","} NF == 5 {a = $1; b = $2; c = $3; $1 = $1; print; next} {$4 = $1; $5 = $2; $1 = a; $2 = b; $3 = c; print}' inputfile

分成多行:

awk 'BEGIN {
        OFS = ","
    } 
    NF == 5 {
        a = $1; 
        b = $2; 
        c = $3; 
        $1 = $1; 
        print; 
        next
    } 
    {
        $4 = $1; 
        $5 = $2; 
        $1 = a; 
        $2 = b; 
        $3 = c; 
        print
    }' inputfile

执行$1 = $1会强制使用新的OFS重新组合该行。

答案 2 :(得分:0)

awk(和tr)解决方案,不是特别优雅:

awk 'BEGIN { OFS = ","}
  { if (NF == 5) {
    split($0, a); print $1, $2, $3, $4, $5
  } else {
    print a[1], a[2], a[3], $1, $2
  } }' | tr -d ' \t'

答案 3 :(得分:0)

假设文件以制表符分隔。

您可以迭代每一行,并将split("\t")应用于每一行,例如

for line in lines:
    result = line.split("\t")

如果len(结果)是5,那么你点了一个新的部分。您可以按原样解压缩值

h1, h2, h3, v1, v2 = result

否则,它是

v1, v2 = result

然后,您可以使用",".join([h1, h2, h3, v1, v2])打印出变量。

至于第二个问题,没有看到文件中的不可见字符,很难分辨。例如,您可以在vi中使用“set list”来查看它们。

答案 4 :(得分:0)

使用awk:

awk 'BEGIN {OFS=","} /^[^ ]/ {f1=$1; f2=$2; f3=$3; f4=$4; f5=$5} /^[ ]/ {f4=$1; f5=$2}  {print f1,f2,f3,f4,f5}' < input.txt

答案 5 :(得分:0)

使用awk:

awk 'BEGIN{OFS="\t";} NF==2{print a,b,c,$1,$2}{};NF==5{a=$1; b=$2; c=$3;print $1,$2,$3,$4,$5}{}' logfile 

首先将输出字段分隔符设置为选项卡(您可以根据需要更改它),然后查看该行中有多少列。如果有5,则将前三个设置为等于变量a,b和c,然后将它们全部打印出来。

如果只有两列,则打印a,b和c(即最后一行的前三列),然后是该行的两列。

<强>更新

我没有注意到只有三列的线!下面的awk命令应该按照您的指定输出:

awk 'BEGIN{OFS="\t";} $1~/^[a-z]/{a=$1; b=$2; c=$3;print $1,$2,$3,$4,$5}{}$1!~/^[a-z]/{print a,b,c,$1,$2}{}' logfile

这与之前的工作方式类似,但会查看第一个字段是以字母开头而不是查看列数。如果需要,可以使这个正则表达式更具体。

答案 6 :(得分:0)

你可以尝试这样的事情来开始 -

awk 'NF>3{a=$1;b=$2;c=$3;$1=$1;print;next}NF<3{d=$1;e=$2;print a,b,c,d,e;next}{$1=$1;}1' OFS=',' file

答案 7 :(得分:-1)

一个简单的grep就可以做到

$ cat so.txt 
xyz123 2.000 -0.3974 0.0 hij123
6.0 lmn123
8.7 efg123
13.9 uvw123
28.5 rst123
abc123 10.000 0.1943 0.0 wxy123
10.7 xyz123
19.9 pqr123
20.6 stu123
20.6 klm123
def123 50.000 -0.2595 19.2 jkl123
26.1 stu123
27.1 def123
27.1 ghi123
27.6 abc123
$ cat so.txt | grep "-"
xyz123 2.000 -0.3974 0.0 hij123
def123 50.000 -0.2595 19.2 jkl123