使用 sed 修改文件时应该转义哪些字符?

使用 sed 修改文件时应该转义哪些字符?

我正在使用以下 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 有一个允许换行、空格和标签嵌套的规范——所有这些都是正则表达式处理得非常糟糕的。

真正的答案是“使用解析器”。

我建议perlXML::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命令中。

相关内容