1

我有一个像下面这样的文件

  <AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10" STATUS="0" SQLTEXT="show databases"/>
  <AUDIT_RECORD TIMESTAMP="2013-07-29T17:27:53" NAME="Quit" CONNECTION_ID="12" STATUS="0"/>
  <AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10" STATUS="0" SQLTEXT="show grants for root@localhost"/>
  <AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10" STATUS="0" SQLTEXT="create table stamp like paper"/>

在这里,每条记录都以开头<AUDIT_RECORD和结尾,"/>并且该记录可能分布在多行中。

我的要求是显示如下结果

  <AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10" STATUS="0" SQLTEXT="show databases"/>
  <AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10" STATUS="0" SQLTEXT="show grants for root@localhost"/>
  <AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10" STATUS="0" SQLTEXT="create table stamp like paper"/>

为此我使用了

sed -n "/Query/,/\/>/p" file.txt

但它显示的是整个文件,包括带有字符串“Quit”的记录。

任何人都可以帮我解决这个问题吗?另外请让我知道是否可以完全匹配名为“Query”的字符串(如grep -w "Query")。

4

4 回答 4

4

使用 GNU awk,您可以将 RS 设置为多个字符:

$ cat file
<AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query"
                CONNECTION_ID="10" STATUS="0" SQLTEXT="show databases"/>
<AUDIT_RECORD TIMESTAMP="2013-07-29T17:27:53"
        NAME="Quit" CONNECTION_ID="12" STATUS="0"/>
<AUDIT_RECORD
        TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10"
     STATUS="0" SQLTEXT="show grants for root@localhost"/>
<AUDIT_RECORD
        TIMESTAMP="2013-07-30T17:52:29"
        NAME="Query"
        CONNECTION_ID="10"
        STATUS="0"
        SQLTEXT="create table stamp like paper"/>
$
$ gawk -v RS='\\/>\n' -v ORS= '/Query/{print $0 RT}' file
<AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query"
                CONNECTION_ID="10" STATUS="0" SQLTEXT="show databases"/>
<AUDIT_RECORD
        TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10"
     STATUS="0" SQLTEXT="show grants for root@localhost"/>
<AUDIT_RECORD
        TIMESTAMP="2013-07-30T17:52:29"
        NAME="Query"
        CONNECTION_ID="10"
        STATUS="0"
        SQLTEXT="create table stamp like paper"/>
$
$ gawk -v RS='\\/>\n' -v ORS= '/Query/{$1=$1; print $0 RT}' file
<AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10" STATUS="0" SQLTEXT="show databases"/>
<AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10" STATUS="0" SQLTEXT="show grants for root@localhost"/>
<AUDIT_RECORD TIMESTAMP="2013-07-30T17:52:29" NAME="Query" CONNECTION_ID="10" STATUS="0" SQLTEXT="create table stamp like paper"/>
于 2013-08-15T15:41:58.300 回答
3

我同意@choroba 的观点,即 XML 解析器是正确的工具。但是,如果没有可用的,你可以试试这个 awk 脚本:

awk '/Query/{print RS" "$0}' RS='<AUDIT_RECORD' file
于 2013-08-15T13:46:27.097 回答
2

我提出的 sed 解决方案:

sed 's/<[^>]*\"Quit\"[^>]*>//' file.txt

对于跨越多行的记录,请尝试:

sed '{:q;N;s/\n/ /g;t q}' file.txt | sed 's/<[^>]*\"Quit\"[^>]*>//'

添加换行符 RS :

... | sed 's|/>|/>\n|g'
于 2013-08-15T13:55:40.050 回答
2

输入可能是 XML。使用适当的解析器来处理它,尤其是当记录跨越多行时。例如,xsh

open file.xml ;
remove //AUDIT_RECORD[not(@NAME="Query")] ;
save :b ;
于 2013-08-15T13:42:16.480 回答