【问题标题】:Use sed to replace string - only after pattern match使用 sed 替换字符串 - 仅在模式匹配之后
【发布时间】:2016-04-29 13:07:45
【问题描述】:

我有以下 XML:

<xml>

    <bean id="bean1"
         class="class1"
         singleton="false">
        <property name="dbPoolName" value="pool"/>
        <property name="dirName" value="myDir"/>
        <!--              <property name="MyProperty" value="5000"/> -->

    </bean>

    <bean id="bean2"
         class="class2"
         singleton="false">
        <property name="dbPoolName" value="pool"/>
        <property name="dirName" value="myDir"/>
        <!--              <property name="MyProperty" value="5000"/> -->

    </bean>

    <bean id="bean3"
         class="class3"
         singleton="false">
        <property name="dbPoolName" value="pool"/>
        <property name="dirName" value="myDir"/>
        <!--              <property name="MyProperty" value="5000"/> -->

    </bean>
</xml>

我需要取消注释元素:

<!--              <property name="MyProperty" value="5000"/> -->

仅在 id 为“bean3”的 bean 内。然后我需要修改它的值,让它变成 50 而不是 5000。

我尝试过使用以下命令:

grep -A 4 "bean3" file.xml | sed 's/<!--//' | sed 's/-->//' | sed 's/5000/50/'

但我无法在文件中替换它。

我应该使用 sed 和/或 grep 吗?

【问题讨论】:

  • grep 将仅提取与模式匹配的行。其余的被删除。在这种情况下,您也希望保留所有其他行。但是您只想用id="bean3" 修改bean 标签的限制使事情变得复杂。我建议使用实际解析 XML 的东西,但它可能无法获取 cmets。

标签: regex xml sed


【解决方案1】:

如果您使用的是 GNU sed,则可以通过一个命令完成所有操作:

sed '/bean3/,+5s/<!-- *\|-->//g; /bean3/,+5s/5000/50/' file.xml

您只需要运行sed 命令的一个实例。各个 sed 命令用分号分隔,;。在这种情况下,我们只需要两个 sed 命令:

  1. 第一个用空字符串替换&lt;!--(可选地后跟空格)和--&gt; - 使用交替\| 运算符和g(全局)修饰符。
  2. 第二个简单地将5000 替换为50

/bean3/,+5 范围是 GNU 扩展;这确保了上述替换仅在第一次出现bean3 之后的 5 行上执行。此范围用于两个替换命令。

如果您确信 sed 命令可以执行您想要的操作,您可以使用 -i / --in-place 选项更改 file.xml

【讨论】:

    【解决方案2】:

    这是一个 AWK 脚本,它使用 id="bean3" 扫描 bean 标记并取消组合并将 "5000" 更改为 "50" 直到下一个 bean 标记:

    #!/usr/bin/awk
    
    BEGIN{ in_bean3 = 0 }
    $0~/<bean / {  # match start of bean tag
        if ( $0 ~ "id=\"bean3\"" ) {
            # Set flag for desired context
            in_bean3 = 1
            print
            next
        } else {  # clear flag
            in_bean3 = 0
        }
    }
    in_bean3 {  # in desired context
        sub(/<!-- */, "")
        sub(/ *-->/, "")
        sub(/"5000"/, "\"50\"")
    }
    1
    

    注意末尾的1 执行打印行的默认操作。

    【讨论】:

      【解决方案3】:
      $ awk '/<bean id=/{f=(/bean3/?1:0)} f&&gsub(/<!-- *| *-->/,""){sub(/00/,"")} 1' file
      <xml>
      
          <bean id="bean1"
               class="class1"
               singleton="false">
              <property name="dbPoolName" value="pool"/>
              <property name="dirName" value="myDir"/>
              <!--              <property name="MyProperty" value="5000"/> -->
      
          </bean>
      
          <bean id="bean2"
               class="class2"
               singleton="false">
              <property name="dbPoolName" value="pool"/>
              <property name="dirName" value="myDir"/>
              <!--              <property name="MyProperty" value="5000"/> -->
      
          </bean>
      
          <bean id="bean3"
               class="class3"
               singleton="false">
              <property name="dbPoolName" value="pool"/>
              <property name="dirName" value="myDir"/>
              <property name="MyProperty" value="50"/>
      
          </bean>
      </xml>
      

      【讨论】:

        猜你喜欢
        • 2017-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-04
        • 1970-01-01
        • 2014-08-01
        相关资源
        最近更新 更多