我使用的是 Linux,我想用它来删除2 个标签之间的sed
正斜杠 ( )。/
由此:
<file>/text</file>
<file>/text2</file
<file>/text</file>..
对此
<file>text</file>
<file>text2</file
<file>text</file>..
测试了很多代码没有成功示例:
sed s'/<file>/s|^\.{1,2}/||' fileout
你能帮我吗?
答案1
给定一个格式良好的 XML 文件,例如
<?xml version="1.0"?>
<root>
<file>/text</file>
<file>/text2</file>
<file>/text</file>
<file>other text</file>
</root>
file
...如果值以 开头,您可以使用 XMLStarlet 删除每个节点值的第一个字符/
:
xmlstarlet edit \
--update '//file[starts-with(text(), "/")]' \
--expr 'substring(text(), 2)' \
myfile.xml
或者,使用更短的语法,
xmlstarlet ed \
-u '//file[starts-with(text(), "/")]' \
-x 'substring(text(), 2)' \
myfile.xml
这将查找file
整个输入文档中值以 开头的每个节点/
,然后使用 删除该第一个字符substring()
。
结果:
<?xml version="1.0"?>
<root>
<file>text</file>
<file>text2</file>
<file>text</file>
<file>other text</file>
</root>
这(以及下面的)将处理其值包含嵌入换行符的节点。
您是否想检测/
值中的任何位置,而不仅仅是在开始处,如果您想将它们全部删除,您可以使用contains()
andtranslate()
来代替:
xmlstarlet edit \
--update '//file[contains(text(), "/")]' \
--expr 'translate(text(), "/", "")' \
myfile.xml
或者只是(因为如果其中translate()
没有值,调用将使值保持不变),/
xmlstarlet edit \
--update '//file' \
--expr 'translate(text(), "/", "")' \
myfile.xml
给定这个输入文件:
<?xml version="1.0"?>
<root>
<file>text/</file>
<file>/text/2</file>
<file>te/x/t/</file>
<file>other text</file>
</root>
...上面的命令将产生以下结果:
<?xml version="1.0"?>
<root>
<file>text</file>
<file>text2</file>
<file>text</file>
<file>other text</file>
</root>
答案2
输入(固定语法)XML
文件(错过了>
第二个节点的关闭file
):
<r>
<file>/text</file>
<file>/text2</file>
<file>/text</file>
</r>
具有现代语法和正确的XPath
功能fn:replace()
(有点sed
for XPath
,允许使用正则表达式和捕获组版本XPath
>= 2),使用XQuery
,您可以执行以下操作:
xidel --xquery '
<r>{
for $x in //file
return <file>{replace($x, "^/(.*)", "$1")}</file>
}</r>
' --output-format=xml file.xml
得出:
<?xml version="1.0" encoding="UTF-8"?>
<r>
<file>text</file>
<file>text2</file>
<file>text</file>
</r>
如果您需要即时编辑文件,请使用sponge
以下工具GNU
more-utils
:
xidel ... file.xml | sponge file.xml
- 正则表达式概述
XPath/XQuery
https://www.regular-expressions.info/xpath.html XPath
是 的子集XQuery
。查看xpath-xquery-和-xpointer 之间的差异xidel
是操作 HTML/XML 的瑞士军刀。- 您还可以使用
XQuery
处理器(开源)BaseX
执行XQuery
表达式
答案3
如果输入的每一行只有两个正斜杠,您可以尝试以下 awk 命令:
$ awk 'BEGIN{OFS=FS="/"}{printf "%s", $1;print$2,$3}' input_file
<file>text</file>
<file>text2</file
<file>text</file>
您需要根据要删除的正斜杠重新定位 printf 和 print 。
答案4
使用乐(以前称为 Perl_6)
...使用 Raku 的(社区支持的)XML
模块:
~$ raku -MXML -e 'my $xml = open-xml( $*ARGFILES.Str );
for $xml.elements( :RECURSE(0), :TAG{"file"} ) -> $E {
my $old = $E.contents[0];
my $new = XML::Text.new( text => $old.text.subst(/^ "/" /) );
$E.replace( $old, $new );
}; .say for $xml;' file.xml
Raku 是 Perl 家族中的一种编程语言,具有高级功能语法用于解析文本。上面使用了它的原生XML语法引擎,Raku的面向对象XML
模块解析输入XML
文件。 XML 元素因此被识别并且可以被迭代。
仅正则表达式(例如sed
)解决方案的一个问题XML
是替换往往是混杂的:您通常很难将替换限制为仅限于某些深度/标签。在带有 -module 的 Raku 中XML
,您可以(例如)将替换限制为 1)。顶层和 2)。仅在<file>
TAG 内。这是通过将代码设置为在elements
限制条件下进行迭代来完成的:RECURSE(0), :TAG{"file"}
。在这里,:NEST
也可以添加 来仅迭代EVEN
节点。
[如果您想迭代所有TAG
深度的所有 s,不用担心:只需设置:RECURSE(Inf)
和删除:TAG
命名参数,这会将:TAG
限制设置为 False ]。
这样就确定了,每个元素的内部(即非TAG)contents[0]
都被赋值给变量$old
,它实际上是一个XML::Text
对象。该$old
对象被.text
提取到一个字符串中,并且subst
没有任何内容来删除有问题的"/"
正斜杠。使用现已更正的键/值对XML::Text.new
创建 ( )新的 ( ) 对象。从这里开始,-module 的例程完成了工作:。$new
text => 'value'
XML
replace
replace( $old, $new )
输入示例(感谢@Kusalananda!):
<?xml version="1.0"?>
<root>
<file>/text</file>
<file>/text2</file>
<file>/text</file>
<file>other text</file>
</root>
示例输出(前导 -/
已从 <file> 标记中删除):
<?xml version="1.0"?><root>
<file>text</file>
<file>text2</file>
<file>text</file>
<file>other text</file>
</root>
https://github.com/raku-community-modules/XML
https://raku.land/?q=XML
https://rakudo.org/
https://raku.org