【问题标题】:awk : how to pass and use array valueawk:如何传递和使用数组值
【发布时间】:2016-02-09 05:34:30
【问题描述】:

我有 awk 脚本,它将从 input1.txt 读取 SEARCH 关键字,它会搜索该 SEARCH 字符串 存在于input2.xml

$ cat myAwk.awk
NR==FNR {
keywordArray[NR]=$0;
next;
}

/<record / { i=1 }
i { a[i++]=$0 }
/<\/record>/ {
    if (found) {
        for (i=1; i<=length(a); ++i) print a[i] >> result.txt
    }
    i=0;
    found=0
}
/<keyword>KEYWORD1<\/keyword>/ { found=1 }
/<keyword>KEYWORD2<\/keyword>/ { found=1 }
.....

这是我需要帮助的地方。我需要传递存储在keywordArray中的KEYWORD值。

$ cat input1.txt
KEYWORD1
KEYWORD2
KEYWORD3
...

$ cat input2.xml
<record category="xyz">
<person ssn="" e-i="E">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<names>
<first_name/>
<last_name></last_name>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>KEYWORD1</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>KEYWORD1 is present in abc for xyz reason</detail>
</external_sources>
</details>
</record>

<record category="abc">
<person ssn="" e-i="F">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<names>
<first_name/>
<last_name></last_name>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>DONTSEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is not present in abc for xyz reason</detail>
</external_sources>
</details>
</record>

$ awk -f myAwk.awk input1.txt input2.xml

【问题讨论】:

  • 您的预期输出是什么?
  • 预期输出是从&lt;record&gt;&lt;/record&gt; 的整个记录​​内容应写入result.txt。只有&lt;keyword&gt;标签值与KEYWORDS匹配的记录

标签: bash shell awk scripting


【解决方案1】:

你可以使用这个awk

awk 'NR==FNR{keywords[$0]++;next} /^<record/{p=1;data=""} p{data = data RS $0;} /^<\/record/{for(key in keywords){if(data ~ key){print data}}}' input1.txt input2.xml

更具可读性awk:

awk 'NR==FNR{keywords[$0]++;next}
     /^<record/{p=1;data=""} 
     p{data = data RS $0;} 
     /^<\/record/{for(key in keywords){if(data ~ key){print data}}}' input1.txt input2.xml

【讨论】:

  • 我有KEYWORD1KEYWORD2KEYWORD3(3 个关键字)。这与 2 个&lt;record&gt;..&lt;/record&gt; 内容匹配。因此,输出为 3*2=6 条记录内容。搜索逻辑似乎是错误的。另外,我没有收到RS。似乎它没有被赋予任何价值。
【解决方案2】:

I need to pass KEYWORD value stored in keywordArray. - 不,你不需要,你只需要首先不使用数组来存储它。只需将我在https://stackoverflow.com/a/35211943/1745001 中给你的答案调整为:

$ awk  '
      NR==FNR{keys=keys sep $0; sep="|"; next}
      {ORS=RT} $0~"<keyword>("keys")</keyword>"
  ' input1.txt RS='</record>\n' input2.xml

以上内容未经测试,因为您第一次没有接受答案,所以我不想花太多精力来修改它。不过它应该很接近,希望你能明白。

【讨论】:

  • 我不得不接受另一个答案,因为它接近我期望的答案。顺便说一句,是我对您在此处链接的答案投了赞成票。
  • 没问题,我只是不想在一个不是您想要的答案上付出太多努力。
【解决方案3】:

我要么将 input1.txt 重写为设置关键字数组的 ba​​sh 文件。 这样您就可以使用源代码调用脚本,并且数组将在调用脚本中设置。

否则你可以像这样循环输入:

input=$(cat $0)
delimiter="\n" #I don't know that this works, otherwise you'll have to replace the newlines with something else
i=0
j=0
while [ ${#input} -gt 0 ]
do
    if [ ${input:$j:1} == delimiter ]
    then
        keywordArray[i]=${input:0:$((j-1))}
        input=${input:$((j+1))}
        j = 0
        ((++i))
    else
        ((++j))
    fi
done

【讨论】:

  • 如果这些是 shell 分配,= 符号周围不能有空格。如果它们是 awk 分配,while 不会使用 dodone。您还需要处理whileif 语句中的条件,无论是shell 还是awk — 但所需的工作取决于它是shell 还是awk。总的来说,我同意您的第一段:使用awksed 或其他东西将关键字列表转换为所需的awk 脚本,然后运行结果。
  • 谢谢你告诉我,我很久没有用 bash 编程了。
  • 更好,但在大多数机器上没有命令++i++j。您可能在 Bash 中想到了 ((++i))((++j))。 POSIX 将使用$((…)),我保留判断是否可以使用增量。此外,cat $0 可能会将脚本列在input 中,假设 Bash 为脚本提供了一个有效的路径名 $0
  • @S.Klumpers keywordArray[i]=${input:0:$((j-1))} 看起来像是给keywordArray 赋值。但是,在从 XML 文件的内容中进行搜索时,keywordArray 在哪里使用?
  • 我不知道,我以为您在将 input1.txt 转换为数组时遇到问题。例如,要搜索 input2.xml,您可以遍历数组并遍历每个关键字的 inpu2.xml。
猜你喜欢
  • 2020-09-09
  • 2016-07-28
  • 1970-01-01
  • 2016-07-04
  • 1970-01-01
  • 2017-11-19
  • 2018-03-26
  • 1970-01-01
  • 2016-01-11
相关资源
最近更新 更多