【问题标题】:grep return matching line and n lines before matching recordgrep 在匹配记录之前返回匹配行和 n 行
【发布时间】:2021-09-26 23:01:20
【问题描述】:

我有一个受限的 bash(在其他工具中有 grep 和 sed,但没有 awk),我试图用它来快速自动化一些日常工作。我目前正在使用“grep 关键字文件名 -b3”,并想弄清楚如何在我拥有的非常有限的工具中更有效地做到这一点。

我如何使用 bash 对符号“111AA2026”进行 grep,获取匹配行上方 3 行的“记录”名称,包括匹配行本身的 XML 文件,如下所示:

<record name="111111H2" />
<items>
  <field name="Electronic Identifier" value="1"/>
  <field name="Symbol" value="111AA2026"/>
  <field name="Full Symbol" value="111AA202622MARFUT"/>
  <field name="System Identifier" value="1"/>
  <field name="System Identifier Description" value="Description"/>
</items>
<record name="111111N1" />
<items>
  <field name="Electronic Identifier" value="2"/>
  <field name="Symbol" value="111AA2026"/>
  <field name="Full Symbol" value="111AA202621JULFUT"/>
  <field name="System Identifier" value="2"/>
  <field name="System Identifier Description" value="Description"/>
</items>
<record name="111111Q1" />
<items>
  <field name="Electronic Identifier" value="3"/>
  <field name="Symbol" value="111AA2026"/>
  <field name="Full Symbol" value="111AA202621AUGFUT"/>
  <field name="System Identifier" value="3"/>
  <field name="System Identifier Description" value="Description"/>
</items>
<record name="111111U1" />
<items>
  <field name="Electronic Identifier" value="4"/>
  <field name="Symbol" value="111AA2026"/>
  <field name="Full Symbol" value="111AA202621SEPFUT"/>
  <field name="System Identifier" value="4"/>
  <field name="System Identifier Description" value="Description"/>
</items>
<record name="111111Z1" />
<items>
  <field name="Electronic Identifier" value="5"/>
  <field name="Symbol" value="111AA2026"/>
  <field name="Full Symbol" value="111AA202621DECFUT"/>
  <field name="System Identifier" value="5"/>
  <field name="System Identifier Description" value="Description"/>
</items>

请注意,实际文件中有多个不同的“符号”值

样本输出

<record name="111111H2" />
 <field name="Symbol" value="111AA2026"/>
--
<record name="111111N1" />
 <field name="Symbol" value="111AA2026"/>
--
<record name="111111Q1" />
 <field name="Symbol" value="111AA2026"/>
--
<record name="111111U1" />
 <field name="Symbol" value="111AA2026"/>
--
<record name="111111Z1" />
 <field name="Symbol" value="111AA2026"/>

我面临的主要挑战是 grepping 一个匹配结果,它给了我匹配行和上面的 3 行,而不是如何获取 XML 文件的属性

【问题讨论】:

  • 你有xmllintPerl吗?
  • 不,我无法访问受限 bash 中的那些
  • @louisxie 我知道您已经问过一个(现已删除)关于将相同的 XML 转换为一些 CSV 行的问题。我认为这对sed 来说是一个很好的挑战,所以如果你感兴趣,我创建了一个脚本,只使用sed 来完成你想要的转换:gist.github.com/igstan/5ffddceba4a6f0516d93cd10ffce8582 这个问题可能有更好的方法,比如使用awk,但是……这是一个有趣的挑战:)
  • @IonuțG.Stan 哦,哇,非常感谢!是的,我已将其删除,因为有人无助地关闭了我的问题。我非常想要我的答案,并且不希望我的下一个问题因为重复而再次关闭,所以我重新发布并重新调整了它。我真的很感激你帮助我解决了下一部分的麻烦!
  • @louisxie 很高兴我能帮上忙。如果您对该脚本还有其他问题,请告诉我,因为我知道 sed 可能非常令人生畏,但它也非常吸引人。

标签: bash sed grep


【解决方案1】:

不确定这是否是您要查找的内容,但它输出的内容与您在示例输出中给出的内容非常相似。

cat temp.xml \
  | grep -B3 '"111AA2026"' \
  | sed -n '/<record/p;/"Symbol/p'
# The -n flag disables printing of all lines, which is what sed
# does by default, so we need to handle printing ourselves using
# the "p" command.
sed -n '
  # [p]rint all lines that contain: <record
  /<record/ p
  # [p]rint all lines that contain: "Symbol
  /"Symbol/ p
'

【讨论】:

  • 您介意解释一下 sed 部分的工作原理吗?
【解决方案2】:

这可能对你有用(GNU sed):

sed -nE '/record/{:a;N;/Symbol/!ba;/111AA2026/s/(\n).*(\1.*)/\2\1--/p}' file

收集recordSymbol 之间的行,如果这些行包含文字111AA2026,则打印集合的第一行和最后一行以及分隔符--

仅使用 grep 的替代方案:

grep -B3 '111AA2026' file | grep 'record\|"Symbol"\|--'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多