【问题标题】:reading semi-formatted data读取半格式化数据
【发布时间】:2012-08-13 04:57:29
【问题描述】:

我对 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

感谢任何帮助。

【问题讨论】:

  • 首先做一个AWK tutorial,然后自己尝试一些事情。 SO 非常适合获得有关您遇到的特定编程(相关)问题的帮助。 “任何帮助”相当广泛。查看 SO 的 FAQ 以查看在 SO 上要问什么,不该问什么。祝你好运。

标签: parsing awk


【解决方案1】:

第一步应该是将看似 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-process

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-解决方案最适合您,但是这使您有可能实现进一步的逻辑......

【讨论】:

  • 没错,列的长度是固定的。照你说的做肯定会奏效。我会试试看,让你知道会发生什么。谢谢!
  • @DennisWilliamson 当然,我只是想展示如何通过将这些问题分解为更简单的“原子”任务来解决这些问题......
【解决方案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

【讨论】:

  • 这似乎没有为我返回任何东西。
  • 可能是因为间距有制表符,仅从图像很难分辨。我刚刚从您粘贴在问题中的示例文本行开始工作。我会更新它来处理标签...
  • 你是对的,它们是通过重复的空格分隔的。伙计,这真的是一个很好的解决方案。非常感谢。
猜你喜欢
  • 2016-05-19
  • 2014-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 1970-01-01
相关资源
最近更新 更多