繁体   English   中英

如何从文件中删除文本块

[英]How to remove blocks of text from file

编辑:在OS X中执行之前没有提到

我正在尝试创建一个bash脚本,该脚本将从文件中删除一些块并将结果保存到另一个。

我要过滤的文件内容应如下所示:

<element>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
</element>
<element>
    <subElement name="removeme"/>
    <subElement name="removeme"/>
    <subElement name="removeme"/>
</element>
<element>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
</element>

我要删除的是包含<element></element>标记的组,其中包含子元素<subElement name="removeme"/>

可以确保没有组将“ removeme”和“ leaveme”元素混合在一起。

我知道如何使用这样的正则表达式来做到这一点:

<element>(?:(?!/elem).)*"removeme".*?</element>

但是我真的对如何在Shell脚本中执行操作迷失了,找到了有关sed的一些信息,但不了解如何完成。

谢谢。

正则表达式当然是解析XML的错误工具 您想要一个XML处理工具来删除与xpath匹配的节点//element[subElement[@name="removeme"]]

  • 具有subElement子项的element节点,该子element节点具有name属性,其值为removeme

使用xmlstarlet

xmlstarlet ed -d '//element[subElement[@name="removeme"]]' << ENDXML
<elements>
   <element>
      <subElement name="leaveme"/>
      <subElement name="leaveme"/>
      <subElement name="leaveme"/>
   </element>
   <element>
      <subElement name="removeme"/>
      <subElement name="removeme"/>
      <subElement name="removeme"/>
   </element>
   <element>
      <subElement name="leaveme"/>
      <subElement name="leaveme"/>
      <subElement name="leaveme"/>
   </element>
</elements>
ENDXML
<?xml version="1.0"?>
<elements>
  <element>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
  </element>
  <element>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
  </element>
</elements>

接下来的想法(基于Jotne的here )是将文件的所有行收集到lines数组中。 <element></element>标记的位置分别保存在i_starti_end 如果看到<subElement name="removeme"/> ,则将found设置为1 (true)。 i_end有条件地设置为0 ,如果found如果是端部元件的真实或行号(数组索引) found是不正确的。 如果i_end不为零,则打印开始标记和结束标记之间的块。

awk '
  { lines[NR] = $0 }
  /<element>/   { i_start = NR }
  /<\/element>/ { i_end = found ? 0 : NR; found = 0 }
  /<subElement name="removeme"\/>/ { found = 1 }
  i_end {
    for (i = i_start; i <= i_end; i++)
      print lines[i]
    i_end = 0;
  }
' file

使用gnu awk可以这样:

awk -v RS="<element>" '!/removeme/ && NR>1{print RS $0}' file
<element>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
</element>

<element>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
    <subElement name="leaveme"/>
</element>

通过将RS设置为<element>您告诉awk以块模式工作,它以<element>开头
然后!/removeme/告诉awk不要打印带有removeme数据的块。

使用sed:

sed -n '
    /<element>/h
    /<element>/!H
    /<\/element>/{g;/<subElement name="removeme"\/>/!p;}
' file

/<element>/h命令在将保持空间与模式空间内容匹配时进行初始化。

如果行与<element>不匹配,则/<element>/!H命令会将模式空间内容追加到保留空间。

/<\\/element>/{g;/<subElement name="removeme"\\/>/!p}命令测试结束标记,并在匹配时执行以下两个命令:

  1. 填充的保留空间将复制到模式空间。 现在,正则表达式将针对包含整个element块的更新后的模式空间进行测试。
  2. 正则表达式寻找过滤子元素值; 如果没有匹配,将打印出图案空间。

如何删除`

[英]How to remove `<a href="file://a>`keep this text`</a>` using sed or perl?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM