需要帮助通过UNIX命令解析文件

时间:2014-08-30 07:34:39

标签: unix

我有一个看起来像这样的行的文件

LINEID1:FIELD1=ABCD,&FIELD2-0&FIELD3-1&FIELD4-0&FIELD9-0;
LINEID2:FIELD1=ABCD,&FIELD5-1&FIELD6-0;
LINEID3:FIELD1=ABCD,&FIELD7-0&FIELD8-0;

LINEID1:FIELD1=XYZ,&FIELD2-0&FIELD3-1&FIELD9-0
LINEID3:FIELD1=XYZ,&FIELD7-0&FIELD8-0;

LINEID1:FIELD1=PQRS,&FIELD3-1&FIELD4-0&FIELD9-0;
LINEID2:FIELD1=PQRS,&FIELD5-1&FIELD6-0;
LINEID3:FIELD1=PQRS,&FIELD7-0&FIELD8-0;

我只对以LINEID1开头的行感兴趣,并且只对该行中的某些元素(FIELD1,FIELD2,FIELD4和FIELD9)感兴趣。输出应该如下所示(no& signs.can替换为|)

FIELD1=ABCD|FIELD2-0|FIELD4-0|FIELD9-0;
FIELD1=XYZ|FIELD2-0|FIELD9-0;
FIELD1=PQRS|FIELD4-0|FIELD9-0;

如果需要其他信息,请告诉我,我会在编辑中发布。谢谢!

3 个答案:

答案 0 :(得分:4)

这不完全是你所要求的,但没有其他人在回答,而且你开始时非常接近!

awk -F'[&:]' '/^LINEID1:/{print $2,$3,$5,$6}' OFS='|' file

<强>输出

FIELD1=ABCD,|FIELD2-0|FIELD4-0|FIELD9-0;
FIELD1=XYZ,|FIELD2-0|FIELD9-0|
FIELD1=PQRS,|FIELD3-1|FIELD9-0;|

-F将输入字段分隔符设置为冒号或符号。然后它查找从LINEID1:开始的行并打印您需要的字段。 OFS将输出字段分隔符设置为管道符号|

答案 1 :(得分:2)

Pure awk:

awk -F ":" ' /LINEID1[^0-9]/{gsub(/FIELD[^1249]+[-=][A-Z0-9]+/,"",$2); gsub(/,*&+/,"|",$2); print $2} ' file

更新以提供正确的格式并省略LINEID11等...

输出:

FIELD1=ABCD|FIELD2-0|FIELD4-0|FIELD9-0;
FIELD1=XYZ|FIELD2-0|FIELD9-0
FIELD1=PQRS|FIELD4-0|FIELD9-0;

说明:

awk -F ":" - 分为LHS($ 1)和RHS($ 2),因为输出只需要RHS

/LINEID1[^0-9]/ - 仅返回与LINEID1匹配的行,同时忽略LINEID11,LINEID100等......

gsub(/FIELD[^1249]+[-=][A-Z0-9]+/,"",$2) - 删除RHS上不是1,4或9的所有字段

gsub(/,*&+/,"|",$2) - 清理RHS上的剩余分隔符

答案 2 :(得分:1)

要使用Unix命令行从数据中选择,请使用grepawkperlpython或{{1} (按功率和可能的复杂程度递增)。

要从数据中选择,请使用rubycut或之前提到的脚本语言之一。

首先,让我们只得到awk的行(假设输入位于名为LINEID1的文件中)。

input

将输出以grep '^LINEID1' input 开头的所有行。

接下来,提取我们关心的列:

LINEID1

最后一行在grep '^LINEID1' input | # extract lines with LINEID1 in them cut -d: -f2 | # extract column 2 (after ':') tr ',&' '\n\n' | # turn ',' and '&' into newlines egrep 'FIELD[1249]' | # extract only fields FIELD1, FIELD2, FIELD4, FIELD9 tr '\n' '|' | # turn newlines into '|' sed -e $'s/\\|\\(FIELD1\\)/\\\n\\1/g' -e 's/\|$//' 行前面插入换行符,并删除任何尾随的“|”。

最后FIELD1模式更具挑战性,因为sed不喜欢其替换模式中的文字换行符。要放置文字换行符,需要使用sed转义符,然后需要在整个字符串中进行转义。

以下是上述命令的输出:

bash

这个命令只用了几分钟就可以了。

即便如此,它还是接近复杂性阈值,因为它们具有出色的字符串处理能力,我会转向perl或ruby。

FIELD1=ABCD|FIELD2-0|FIELD4-0|FIELD9-0; FIELD1=XYZ|FIELD2-0|FIELD9-0 FIELD1=PQRS|FIELD4-0|FIELD9-0; 中的相同脚本可能如下所示:

ruby

在同一输入文件上运行此脚本,将出现与上面相同的输出:

#!/usr/bin/env ruby
#
while line = gets do
  if line.chomp =~ /^LINEID1:(.*)$/
    f1, others = $1.split(',')
    fields = others.split('&').map {|f| f if f =~ /FIELD[1249]/}.compact
    puts [f1, fields].flatten.join("|")
  end
end