awk - 如何提取模式

时间:2013-04-28 11:31:46

标签: awk gawk

询问有关使用awk从文件中提取具有特定行的文本块的说明。

该文件具有以下结构:

<Information>
<CID>_whole_number_A_</CID>
<string>_text_that_is_not_useful_</string>
<string>_text_that_is_not_useful_</string>
<string>_PATTERN_A_</string>
<string>_text_that_is_not_useful_</string>
</Information>
<Information>
<CID>_whole_number_B_</CID>
<string>_PATTERN_B_</string>
<string>_text_that_is_not_useful_</string>
<string>_text_that_is_not_useful_</string>
<string>_text_that_is_not_useful_</string>
<string>_text_that_is_not_useful_</string>
<string>_text_that_is_not_useful_</string>
</Information>

想要将以下模式发送到新文件。

<Information>
<CID>_whole_number_A_</CID>
<string>_PATTERN_A_</string>
</Information>
<Information>
<CID>_whole_number_B_</CID>
<string>_PATTERN_B_</string>
</Information>

有关数据的说明:

  • 该文件包含300,000多个CID项目;每个都有一个独特的整体 号。
  • PATTERNs(_PTERN_A_,_PATTERN_B_等)具有格式 UNII-&lt; 10个字符&gt;。例如:UNII-4J4Z8788N8或UNII-12L95QD6KV。
  • 并非每个CID都有UNII。

关于我的环境的说明:

  • 使用Windows 7并使用GnuWin32实用程序

所以,用英语改写:

  

在FILE_1

     

查找具有UNII的每个CID

     

将过滤后的结果发送到FILE_2

提前感谢您的指示。

=============================================== =========================

好的,我做错了。

在我的第一个实现中,程序只返回“record starts”和“closing tag”,即:

<Information>
</Information>

以下是我如何应用您的说明。

首先,我正在运行Windows,因此更改为FS =“\ r \ n”

第一个正则表达式是UNII,因此更改为/ UNII /.

第二个正则表达式是CID,您在指示中使用了它。那里我没有改变。

对于PATTERN的第二个实例,我改为/ UNII /.

以下是我的替换方式:

BEGIN {
    RS="<Information>"
    FS="\r\n"
}
/UNII/ {
    print RS
    for (i=1;i<NF;i++) {
        if ($i ~ /CID/ || $i ~ /UNII/) {
            print $i
        }
    }
    print "</Information>"
}

因为我使用的是Windows,所以我使用完整路径来执行GnuWin32实用程序和读/写数据。所以我的.bat文件看起来像这样:

C:\bin\awk -f C:\bin\script.awk < C:\Users\Owner\data\input_file.txt > C:\Users\Owner\data\output_file.txt

我做错了什么?

=============================================== ================================== 以下是示例数据:

<Information>
    <CID>1</CID>
    <Synonym>Acetyl carnitine</Synonym>
    <Synonym>O-Acetyl-L-carnitine</Synonym>
    <Synonym>Ammonium, (3-carboxy-2-hydroxypropyl)trimethyl-, hydroxide, inner salt, acetate, DL-</Synonym>
    <Synonym>UNII-07OP6H4V4A</Synonym>
    <Synonym>_20+_more_</Synonym>
</Information>
<Information>
    <CID>10006</CID>
    <Synonym>HYDANTOIN</Synonym>
    <Synonym>UNII-I6208298TA</Synonym>
    <Synonym>53760_FLUKA</Synonym>
    <Synonym>NSC9226</Synonym>
    <Synonym>_20+_more_</Synonym>
</Information>
<Information>
    <CID>10007</CID>
    <Synonym>Lucofen SA</Synonym>
    <Synonym>461-78-9</Synonym>
    <Synonym>EINECS 207-314-9</Synonym>
    <Synonym>STK664067</Synonym>
    <Synonym>DEA No. 1645</Synonym>
    <Synonym>UNII-NHW07912O7</Synonym>
    <Synonym>CHEMBL1201269</Synonym>
    <Synonym>HMS1376E21</Synonym>
    <Synonym>_20+_more_</Synonym>
</Information>

2 个答案:

答案 0 :(得分:1)

这个脚本应该提供一个很好的起点:

BEGIN {
    RS="<Information>"
    FS="\n"
}
/UNII/ {
    print RS
    for (i=1;i<NF;i++) {
        if ($i ~ /CID/ || $i ~ /UNII/) {
            print $i
        }
    }
    print "</Information>"
}

将其保存到script.awk并在样本输入上运行它会产生:

$ awk -f script.awk file
<Information>
    <CID>1</CID>
    <Synonym>UNII-07OP6H4V4A</Synonym>
</Information>
<Information>
    <CID>10006</CID>
    <Synonym>UNII-I6208298TA</Synonym>
</Information>
<Information>
    <CID>10007</CID>
    <Synonym>UNII-NHW07912O7</Synonym>
</Information>

答案 1 :(得分:1)

首先,awk完全是错误的工具。但是使用awk执行此操作的最简单方法是抑制您不想要的行(而不是选择您想要的行):

/Synonym/ && !/UNII/ { next }
{ print }