我需要将字符替换S
为T
:
<episode-num system="onscreen">S1 E12</episode-num>
我期望的结果:
<episode-num system="onscreen">T1 E12</episode-num>
我不知道 Git 是如何深入工作的,我只是用它来替换我的 xml 标签中的那个字符,在论坛中研究我找到了一些信息并尝试了以下命令行:
sed -e :l -e 's@\(<episode-num system="onscreen">.*\)S\([^amp;]\)\(.*</episode-num>\)@\1T\2\3@;tl' guide.xml
但这不起作用,我希望你能帮助我。
答案1
假设您有一些 XML 文档,例如
<data>
<episode-num system="onscreen">S1 E12</episode-num>
<episode-num system="onscreen">S1 S12</episode-num>
<episode-num system="onscreen">T1 S12</episode-num>
</data>
...并且您想要替换节点值中S
的所有字符T
episode-num
从...开始S
。
xmlstarlet
你可以这样做:
xmlstarlet ed -u '//episode-num[starts-with(text(),"S")]' \
-x 'translate(text(),"S","T")' file.xml
这可能会修改任何episode-num
节点,无论它们位于文档中的哪个位置。如果你只想修改特别的节点,然后将//episode-num
XPath 表达式更改为更精确的路径。
鉴于我上面的示例文档,xmlstarlet
上面的命令将产生
<?xml version="1.0"?>
<data>
<episode-num system="onscreen">T1 E12</episode-num>
<episode-num system="onscreen">T1 T12</episode-num>
<episode-num system="onscreen">T1 S12</episode-num>
</data>
与xq
(来自https://kislyuk.github.io/yq/) 与xmlstarlet
上面一样:
xq -x '(.data."episode-num"[] | select (."#text"|startswith("S")))."#text" |= gsub("S";"T")' file.xml
这假设输入文档与我的示例文档具有相同的结构。它使用 XML 解析器解析文档,然后在内部将其转换为 JSON。它调用jq
生成的 JSON 文档来应用给定的表达式,最后再次将所有内容转换回 XML。
对于我正在使用的示例文档,表达式实际应用到的内部 JSON 文档jq
如下所示:
{
"data": {
"episode-num": [
{
"@system": "onscreen",
"#text": "S1 E12"
},
{
"@system": "onscreen",
"#text": "S1 S12"
},
{
"@system": "onscreen",
"#text": "T1 S12"
}
]
}
}
答案2
仅当行包含另一个字符串时才替换某些字符串sed
我们仅替换包含字符串的行free
sed '/free/s/i/I/g' example.txt
'/free/s/i/I/g'
/free/
- 仅当包含此字符串时才替换行s
- sed 的替代命令/i/
- 我们想要匹配什么正则表达式/I/
- 替换匹配的子字符串/g
- 替换标志,对线上的所有匹配项进行重复替换
您的假设的解决方案
你的测试字符串是<episode-num system="onscreen">
假设您有一个包含以下内容的文件:
$ cat test.xml
<data>
<episode-num system="onscreen">S1 E11</episode-num>
<episode-num system="onscreen">S1 E12</episode-num>
<episode-num system="onscreen">T1 E13</episode-num>
<some data>S1 E1</episode-num>
</data>
您的 sed 解决方案是:
$ sed '/<episode-num system="onscreen">/s/S/T/g' test.xml
<data>
<episode-num system="onscreen">T1 E11</episode-num>
<episode-num system="onscreen">T1 E12</episode-num>
<episode-num system="onscreen">T1 E13</episode-num>
<some data>S1 E1</episode-num>
</data>
该解决方案的来源是这里。
答案3
Perl one-ligner 并不是一个好方法。反正:
perl -MXML::DT -e 'print dt("ex1.xml", "episode-num" => sub{$c=~ s/S/T/; toxml})'
在哪里:
-XML::DT
= 导入并使用 XML::DT 模块(在本例中dt
为函数dt( file, processor)
= 使用提供的处理器向下翻译文件episode-num => sub{...}
= 适用sub
于每个元素episode-sum
$c = s/S/T/ ; toxml
= 将元素内容中的 S 替换为 T (=$c) 并重新计算episode
XML 元素
(如有需要sudo cpanm XML::DT
)