我正在使用以下 sed 命令(带字边界):
sed "7 s/\<<Filevalue=.*/>\>/<Filevalue="true"/>/" < config.xml
我收到此错误:
sed: command garbled: 7 s/\<<Filevalue=.*/>\>/<Filevalue="true"/>/
我尝试转义特殊字符但仍然收到相同的错误:
sed "7 s/\<\<Filevalue=.*\/\/\>\>/\<Filevalue=\"true\"\/\>/" < config.xml
我做错了什么?
编辑:
这是一个虚拟 XML。文件值的值可能会有所不同。
XML 内容:
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
答案1
您还必须反斜杠不能用作分隔符的斜杠,或者使用不同的分隔符:
sed "7 s%\<<Filevalue=.*/>\>%<Filevalue="true"/>%"
此外,您不能在双引号中包含双引号而不使用反斜杠,或者切换到单引号。
此外,单词不能以 a 开头<
,因此\<<
永远不会匹配。
答案2
你做错的是你试图用正则表达式解析 XML。这是一个坏主意——它有时有效,但它会产生脆弱的代码。 XML 有一个允许换行、空格和标签嵌套的规范——所有这些都是正则表达式处理得非常糟糕的。
真正的答案是“使用解析器”。
我建议perl
并XML::Twig
作为选项 - 但还有其他选项:
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new(
'pretty_print' => 'indented',
'twig_handlers' => {
'File' => sub { $_->set_att( 'value', 'true' ) }
}
);
$twig->parsefile('config.xml');
$twig->print;
我对 XML 的内容做出了某些假设 - 如果您准备提供更广泛的示例,我将仔细检查并确保其按缩进方式工作。
编辑:
根据您发布的代码片段 - 这不是有效的 XML,因此请忽略上面的内容。不过,我仍然建议您不要使用看起来有点像 XML 的东西,之所以这样称呼,是output.xml
因为这是一条通向各种痛苦和不幸的道路。
我上面的代码适用于:
<xml>
<File value="false"/>
<File value="false"/>
<File value="false"/>
<File value="false"/>
<File value="false"/>
<File value="false"/>
<File value="false"/>
</xml>
您可以在此处检查 XML 有效性:http://www.xmlvalidation.com/index.php?id=1&L=0
如果我们抛开它不是 XML 的事实 - 这是有效的:
#!/usr/bin/perl
use strict;
use warnings;
while ( <DATA> ) {
#amend just line 7
if ( $. == 7 ) { s,<Filevalue=".*">,<Filevalue="true">,; }
print;
}
__DATA__
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
您可以通过以下方式之一:
perl -nle 'if ( $.==7) {s,<Filevalue=".*">,<Filevalue="true">,g;} print;' notxml.txt
答案3
choroba 基本上是正确的......但他对双引号产生了误导:这对 sed 来说不是问题,但对 shell 来说是问题。
您只需要转义* [ ] \ .
和分隔符(默认情况下/
)。对于你的情况,我相信这最有效:
sed '7s%<<\([^>]*\)>>%<\1>%' file
如果有效,请使用该-i
选项在文件中替换它。
解释:
- 该
\( \)
组表达式在右侧被替换为\
- 吞噬
[^>]*
所有字符直到下一个直角括号。 - 因此,不正确的双括号内的任何内容都将被替换为双括号内的相同表达式。注意,这只会发生一次在第 7 行,除非您将
g
标志附加到s
命令中。