如何使用sed / awk解析文件的内容?

时间:2016-05-26 00:41:04

标签: bash awk sed grep

我的输入文件的内容采用以下格式,其中每列用“空格”

分隔
string1<space>string2<space>string3<space>YYYY-mm-dd<space>hh:mm:ss.SSS<space>string4<space>10:1234567890<space>0e:Apple 1.2.3.4<space><space>string5<space>HEX  

“0e:Apple 1.2.3.4”后面有2个“空格”,因为此字段/列中没有第14位数字。整个“0e:Apple 1.2.3.4space”被视为该列的单个值。

在第7列中, 10:表示以下字符串中的字符数。

在第8列中, 0e:表示十六进制值14.因此,HEX值提及后面字符串中的字符数。

喜欢:

"0e:Apple 1.2.3.4 "--> this is the actual value in 8th column without " "  
    (I've mentioned " " to show that the 14th digit is empty)  

It's counted as  
0e:A p p l e   1 . 2 .   3  . 4    
   | | | | | | | | | |   |  | | |  
   1 2 3 4 5 6 7 8 9 10 11 12 1314  

让我们将输入文件中的第一行视为:

string1 string2 string3 yyyy-mm-dd 23:50:45.999 string4 10:1234567890 0e:Apple 1.2.3.4  string5 001e  

其中:

  • string1是第1列中的值
  • string2是第二列中的值
  • string3是第3列中的值
  • 第四次
  • yyyy-mm-dd
  • 第五次
  • 23:50:50.999
  • 第六次
  • string3
  • 第7位
  • 10:1234567890 //最后没有空格,因为它有10位数字
  • 第8页<终止中的
  • 0e:Apple 1.2.3.4 第9天
  • string5
  • 第10次
  • 001e

预期产出:

string1,string2,string3,yyyy-mm dd,23:50:50.999,string3,1234567890,Apple_1.2.3.4,string5,30  

要求:

  1. 从第7列和第8列消除计数(10:&amp; 0e:
  2. 空格信息Apple1.2.3.4应替换为“_”
  3. 最后一列中的十六进制值应转换为十进制值。
  4. 使用“,”
  5. 替换列之间的“空格”
  6. 我这里仅在第10列使用了十六进制值。如果它在几列中怎么办?有什么方法可以将其转换为特定的列?
  7. 我尝试过使用它:

    $ cat input.txt |sed 's/[a-z0-9].*://g'  
    

    ,输出为:

    string1,string2,string3,yyyy-mm-dd,45.999,string4,1234567890,Apple,1.2.3.4,,string5,001e  
    

1 个答案:

答案 0 :(得分:2)

这将在您的示例输入中执行您想要的操作:

awk -F "[ ]" '{sub(/.*:/, "", $7) sub(/.*:/, "", $8); printf "%s,%s,%s,%s,%s,%s,%s,%s_%s,%s,%s,%d\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, "0x"$12}' input.txt

部分说明:

awk printf允许您指定输出格式,因此您可以手动指定要与,分隔的字段以及要与_分隔的字段

-F "[ ]"强制字段分隔符为单个空格,以便它知道两个单独空格之间存在空字段。默认行为是允许多个空格成为单个分隔符,根据问题,这不是您想要的。

sub函数允许您进行正则表达式替换,在这种情况下,删除字段7和8中的..:前缀。

对于字段12,我们告诉printf输出一个数字(%d)并将前缀为0x的字符串作为输入,以便将其解释为十六进制。

注意:如果您不希望输出为$8_$9,那么您实际上需要解析十六进制前缀并对字符进行计数以确定场结束。如果是这种情况,我个人更愿意用其他东西来写整篇文章,例如:蟒。