Sed:仅当标记与第一个字符串

时间:2016-05-22 22:40:29

标签: regex xml linux unix sed

我有一个这样的文本文件:

B1=text1
B2=text2
B3=text3

我有以下sed,它会将此文本格式转换为标记之间的文本。

echo "String= Hello World" | sed 's#\([^=]\+\)=\(.*\)#<\1>\2</\1>#'

这个sed给出了这个输出:

<String > Hello World</String >

如果String与B和数字一起使用,例如B45,如何放置标签?所以字符串将是B45

如果String匹配B + number

然后Sed命令给出这个输出(例子)

<B1>text1</B1>
<B2>text2</B2>
<B3>text3</B3>

2 个答案:

答案 0 :(得分:0)

我认为这对你有用:

echo "String= Hllo World" | sed 's#\([^=]\+\)=\(\s*B[0-9]*.*\)#<\1>\2</\1>#'

答案 1 :(得分:0)

请不要使用正则表达式来操作XML。 XML是一种上下文语言。正则表达式不是,所以它永远不会正常工作。充其量,你有一个肮脏的黑客,有一天会因为没有明显的原因而中断,因为它做出的假设是无效的。

请使用解析器。这并不难,但确实意味着你要避免创建脆弱的代码。

perl中的慢手,它是:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $input = "String= Hello World";
my ($tag, $content) = split /=/, $input;

XML::Twig::Elt -> new ( $tag, $content ) -> print;

输出:

<String> Hello World</String>

作为一个更广泛的例子:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $input = "";
my ( $tag, $content ) = split /=/, $input;

my $doc = XML::Twig->new( pretty_print => 'indented_a' ) ;
$doc->set_xml_version("1.0");
$doc->set_encoding('utf-8');
$doc->set_root( XML::Twig::Elt->new('root') );

while (<>) {
   chomp;
   my ( $tag, $content ) = split /=/;
   if ( $content =~ m/^B/ ) {
      $doc->root->insert_new_elt( 'last_child', $tag, $content );
   }
}

$doc->print;

输入:

String= Hello World
tag=B1234 some text here
newtag=fish heads fish heads roly poly fish heads
String=Better fun joy here

给出结果:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <String>Better fun joy here</String>
  <tag>B1234 some text here</tag>
</root>

使用正确的解析器并不太难,如果您需要更多理由:RegEx match open tags except XHTML self-contained tags