【问题标题】:Handling output of the flip-flop operator处理触发器运算符的输出
【发布时间】:2017-08-05 07:24:17
【问题描述】:

我一直在努力使用触发器运算符来替换输入 xml 文件中的特定值。

文件结构如下:

<a>BLE</a>
<-- hur dur -->
<b>12345</b>
<-- hur der -->
<c>VER1.2.3</c>
<-- hur dest -->
<d>VER1.2.3</d>

<a>CLE</a>
<-- hur dur -->
<b>12345</b>
<-- hur der -->
<c>VERX'.Y'.Z'</c>
<-- hur dest -->
<d>VERX'.Y'.Z'</d>

<a>DLE</a>
<-- hur dur -->
<b>12345</b>
<-- hur der -->
<c>VERX".Y".Z"</c>
<-- hur dest -->
<d>VERX".Y".Z"</d>
etc ...

假设我想更改任何特定变量的版本字段(d 和 c)。为简洁起见,让它成为 BLE。我必须首先找到具有 BLE 值的块(第 1-7 行),然后用新值替换字段。

我一直在尝试不同的东西,比如:

perl -pi.bak -ne 'if ( /BLE/ .. /<\/d/ ){ s/VER[[:digit:]]\+\.[[:digit:]]\+\.[A-Z][[:digit:]]\+[A-Z]\?/$ver/}' dur.xml

perl -ne "print if ( /BLE/ .. /<\/d>/ ) " dur.xml | sed "/VER[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+[A-Z]\?/$ver/"

其中 $ver 是一个集合变量 (ver="VERX.Y.Z")。但是第一个对输入文件没有做任何事情(我更喜欢就地做);第二个或多或少地产生了我想要的,但输出仅限于 BLE 块:

<a>BLE</a>
<-- hur dur -->
<b>12345</b>
<-- hur der -->
<c>VERX.Y.Z</c>
<-- hur dest -->
<d>VERX.Y.Z</d>

但是这个输出不能很容易地用 > 重定向到一个文件,因为它会丢弃除 BLE 之外的所有东西。

有什么方法可以像上面描述的那样修改原始文件吗?

非常感谢, 饮酒者

【问题讨论】:

  • 该输入是否应该是真正的 XML?看起来不像。请包含一个确切的文件。
  • ...另外,您的示例数据中没有任何buildversion 字符串...
  • @simbabque 不,它不是真正的 XML - 我正在编辑的文件只有一个 .xml 扩展名 - 但结构有点相似。原来的样子也像这样,只有标签 a、b、c 和 d 有不同的名称
  • @jm666 糟糕,复制粘贴失败。固定
  • 所以文件有标签块和空行,还有那些不是 cmets &lt;-- ... --&gt;?而您只想更改&lt;d&gt;&lt;a&gt;BLE

标签: regex perl shell


【解决方案1】:

这是我看到的完成任务的一种方法

perl -pe's{<d>VER\K.*?(</d>)}{xxx$1} if m{BLE} .. m{</d>}' data.txt

这将在给定范围内的行上用xxx 替换&lt;d&gt;VER 和(第一个)&lt;/d&gt; 之间的任何内容。 \Kpositive lookbehind 的形式,它会丢弃之前的匹配项,因此我们不必捕获它们并将它们放回原处。

-p 每次都会打印 $_,而 s{}{} 会更改它,因此您可以打印所有行,无论是否更改。它和-n(相同但不打印)没有任何意义,但如果你这样做了,那么-p 会覆盖另一个。要使用备份就地更改文件,确实添加-i.bak。见perlrun

如果您需要访问特定数字,您可以改用正则表达式

s{<d>VER\K(\d+)\.(\d+)\.(\d+)</d>}{$1.$new.$3</d>}

为了允许在数字后面添加可选字母,您的代码所暗示的内容,请使用(\d+[A-Z]?)。如果X'X" 中的'" 是实际字符,请调整这个(第一个例子很好)。如果您打算将它们用作“X-prime”(和双质数),请不要 - 这在这里非常具有误导性。

为了获得更大的灵活性,将其转换为脚本,无论如何这可能是个好主意。如果在 shell 脚本中,您可以直接使用变量而不是上面的文字(VERxxx)。


发布的代码中的问题不在于“触发器”(range operator),它只是选择行并且您正确使用。它与正则表达式一起使用,其中在最后一个数字之前有[A-Z],在它之后有另一个。数据只是没有字母,所以不匹配。

另外,请注意\?quantifier ? 转换为文字?,这也不在数据中。

【讨论】:

  • 谢谢@zdim。这对我有用perl -i.bak -pe "s{&lt;d&gt;\K.*?&lt;/d&gt;}{$ver&lt;/d&gt;} if m{BLE} .. m{\/d}" dur.xml
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-15
  • 2018-07-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
相关资源
最近更新 更多