找到最后一次出现的字符串并在sed awk grep下面打印所有内容

时间:2017-06-20 22:40:14

标签: linux bash awk sed grep

您好我有一个大文件,可以快速更新。它存储了很多FIX-ORDER消息。每个订单都包含在以“FIXES”开头的部分中,并以“Committed”结尾。在每个订单部分中,修复消息位于第一部分,后面是第二部分中的其他消息。 请参阅下面的输入样本和输出样本。

简而言之,我喜欢grep文件并逐行打印最后一个订单部分 并确保修复消息也打印在各行上。见下面的第二部分,这是我需要的最终出版物。

如果您能提供帮助,请告诉我

在订单部分中启动文本(让我们称之为订单A)

FIXES LIMIT CHECK ON:

FIX MESSAGE SECTION

FIXES LIMIT CHECK ON: 8=FIX.4.2;9=0;35=D;10=100; (Client.123.600)

修复消息部分+其他日志消息,直到我们到达单词Commit 请注意每行以结束的括号

结束
FIXES LIMIT CHECK ON: 8=FIX.4.2;9=0;35=D;10=100; (Client.123.600)
1234  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
1235  cdghhhh ggg/HIT [19889] INFO JUN 20 17:25:34 Matched  (Found.c.t)
1236  abwwwfg EFG/HIT [12885] debug JUN 20 17:25:34 Matched  (Match.c.t)
Committed 

如果可能,我只想使用一个命令行;输出有两部分。请在回答之前阅读这两个部分:

第一部分)我喜欢使用一个命令从“FIXES LIMIT CHECK ON:”开始的行中将每个订单部分gred到单词Committed,所以基本上

FIXES LIMIT CHECK ON: 8=FIX.4.2;9=0;35=D;10=100; (Client.123.600)
1234  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
1235  cdghhhh ggg/HIT [19889] INFO JUN 20 17:25:34 Matched  (Found.c.t)
1234  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
Committed 

第二部分)

 I like to print each Fix message that is divided by ";" in a new line 
 please note that the last entry of the fix message is (Client.123.600)
 so my final out put should look like this

FIXES LIMIT CHECK ON: 
8=FIX.4.2;
9=0;35=D;
10=100; 
(Client.123.600)
1234  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
1235  cdghhhh ggg/HIT [19889] INFO JUN 20 17:25:34 Matched  (Found.c.t)
1234  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
Committed 

3 个答案:

答案 0 :(得分:1)

修改如下:

tac <data_file> | sed -n -e '/Committed/,/FIXES LIMIT CHECK ON/p ; /FIXES LIMIT CHECK ON/q' | tac | sed -e '/Client/ { s/:\s?/:\n/g ; s/;\s*/;\n/g }'

答案 1 :(得分:0)

grep -n '^FIXES '

为了让批评者高兴,我会解释。

在第一个命令中,tail -1查找以&#39; FIXES&#39;开头的所有行。并给出了行号,cut -d: -f1部分只给出了最后一行,sed -n解析了行号。

在第二个命令中,sed除非我们发送&#34; print&#34;否则不会打印任何内容。命令。我们的&#34; print&#34;命令告诉sed从我们找到的行号打印到#34; Committed&#34;的下一个实例。我们将这些行发送到另一个<?xml version="1.0" encoding="UTF-8"?> <jboss-web xmlns="http://www.jboss.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_5_1.xsd"> <context-root>/</context-root> </jboss-web>,用冒号或分号(我们找到的任何一个)替换冒号和分号(后跟任意数量的空格)和换行符。

答案 2 :(得分:0)

使用GNU awk for gensub():

$ cat tst.awk
inMsgs {
    # Previous line must have been a FIXES.. line and we are
    # now in the messages lines so just append each of them
    # to the msgs variable as they are read.
    msgs = msgs $0 ORS
}
/Committed/ {
    # Found a "Committed" line so this is the end of a complete
    # block of input so save the contents of the current "fix"
    # and "msgs" variables to the "last read block" equivalents
    # and clear the "in messages block" flag.
    lastFix  = fix
    lastMsgs = msgs
    inMsgs   = 0
}
/^FIXES LIMIT CHECK ON:/ {
    # Found a FIXES... line so save that "fix" line, empty
    # the buffer of "msgs" and set the "in messages block flag"
    # so it is set when the next line is read.
    fix      = $0
    msgs     = ""
    inMsgs   = 1
}
END {
    # We have reached the end of the input file so insert newlines
    # where appropriate in the "lastFix" line then print it and
    # then print the lines stored in the "lastMsgs" variable.
    print gensub(/([^:]+:) ([^;]+;)([^;]+;)([^;]+;)([^;]+;) (.*)/,"\\1\n\\2\n\\3\n\\4\n\\5\n\\6",1,lastFix)
    printf "%s", lastMsgs
}

$ awk -f tst.awk file
FIXES LIMIT CHECK ON:
8=FIX.4.2;
9=0;
35=D;
10=100;
(Client.123.600)
1234  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
1235  cdghhhh ggg/HIT [19889] INFO JUN 20 17:25:34 Matched  (Found.c.t)
1236  abwwwfg EFG/HIT [12885] debug JUN 20 17:25:34 Matched  (Match.c.t)
Committed

大多数复杂性是为了确保它只打印最后的完整记录(即以“已提交”结尾的记录)。

这是一个更好的示例输入文件,用于说明为什么需要上述逻辑:

$ cat file
stuff
FIXES LIMIT CHECK ON: 8=FIX.4.2;9=0;35=D;10=100; (Client.123.600)
1231  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
1232  cdghhhh ggg/HIT [19889] INFO JUN 20 17:25:34 Matched  (Found.c.t)
1233  abwwwfg EFG/HIT [12885] debug JUN 20 17:25:34 Matched  (Match.c.t)
Committed
foo
FIXES LIMIT CHECK ON: 8=FIX.4.2;9=0;35=D;10=100; (Client.123.600)
1234  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
1235  cdghhhh ggg/HIT [19889] INFO JUN 20 17:25:34 Matched  (Found.c.t)
1236  abwwwfg EFG/HIT [12885] debug JUN 20 17:25:34 Matched  (Match.c.t)
Committed
bar
FIXES LIMIT CHECK ON: 8=FIX.4.2;9=0;35=D;10=100; (Client.123.600)
1237  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
1238  cdghhhh ggg/HIT [19889] INFO JUN 20 17:25:34 Matched  (Found.c.t)
1239  abwwwfg EFG/HIT [12885] debug JUN 20 17:25:34 Matched  (Match.c.t)

在上述情况下,预期输出将是中间块(具有从1234,1235和1236开始的消息行的那个),而不是最后一个块,因为最后一个块不以Committed结束,因此仍然在通过生成它的任何命令写入输入文件的过程中。因此,文件中的最后一个完整块是中间的,因此预期的输出是由上面的awk命令产生的:

$ awk -f tst.awk file
FIXES LIMIT CHECK ON:
8=FIX.4.2;
9=0;
35=D;
10=100;
(Client.123.600)
1234  abcdefg EFG/HIT [12355] debug JUN 20 17:25:34 Matched  (Match.c.t)
1235  cdghhhh ggg/HIT [19889] INFO JUN 20 17:25:34 Matched  (Found.c.t)
1236  abwwwfg EFG/HIT [12885] debug JUN 20 17:25:34 Matched  (Match.c.t)
Committed