读取半格式化数据

时间:2012-08-16 19:19:03

标签: parsing awk

我对AWK完全不熟悉,但我认为这是解决问题的最佳方法,也是学习AWK的好时机。 我正在尝试读取由模拟程序创建的大型数据文件。输出使人可读,因此其格式不是很一致。输出的示例在此图像中 http://i.imgur.com/0kf8l.png

我需要一种方法来找到像“He 2 4686A -2.088 0.0071”这样的行,通过指定“He 2 4686A”部分并得到以下两个数字。问题是“He 2 4686A -2.088 0.0071”这一行可以出现在表格的任何地方。 我知道如何找到条目“He 2 4686A”,但我不知道它所在的4列中的哪一列。所以我不知道如何解决它后面的值。 一个让我只读下两个单词的命令,或者一旦找到匹配就告诉我模式的位置都会有所帮助。

/ He 2 4686A /找到该行

Ca A 3970A -0.900 0.1100 He 2 4686A -2.088 0.0071 S 3 18.67m -0.371 0.3721 Ar 4 444.7A -2.124 0.0066

感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

第一步应该是将4列记录显示为1列格式......然后使用awk轻松实现,因为您可以过滤前5个字段 - 例如:

echo "He 2 4686A -2.088 0.0071" | \
awk '$1 == "He" && $2 == 2 && $3 == "4686A" {print $4, $5}'

给出了

-2.088 0.0071

所以,对我来说,唯一的挑战是将数据转换为单列格式......而且从看起来很简单的图片来看,因为看起来这些列的长度是固定的,你可以计算。

假设您的列宽为30个字符(很难从图片中分辨出来,请注意标签)并且您的数据位于input_file,那么您可以先将数据“剪切”为4列,然后再进行管道输出到另一个awk - 进程

awk '{
  print substr($0,1,30)
  print substr($0,31,30)
  print substr($0,61,30)
  print substr($0,91,30)
}' input_file | \
awk '$1 == "He" && $2 == 2 && $3 == "4686A" {print $4, $5}'

如果你真的只需要锚点后面的两个数字,那么我会说来自Costa的grep - 解决方案最适合你,但是这可以让你实现更多的逻辑......

答案 1 :(得分:2)

如果你没有使用awkgrep将是最简单的方式......

egrep -o "He 2 4686A \-?[0-9.]+ \-?[0-9.]+" output.txt

编辑:只有在用空格完成间距时才能使用上述内容,这似乎不是你的情况。为了处理标签和/或重复空格...

egrep -o "He[ \t]+2[ \t]+4686A[ \t]+\-?[0-9.]+[ \t]+\-?[0-9.]+" output.txt