如何使用grep,regex或perl提取模式后面的字符串

时间:2011-02-22 16:34:07

标签: regex perl sed html-parsing text-extraction

我有一个看起来像这样的文件:

<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>

我需要在name=后面的引号中提取任何内容,即content_analyzercontent_analyzer2content_analyzer_items

我在Linux机器上这样做,所以使用sed,perl,grep或bash的解决方案很好。

8 个答案:

答案 0 :(得分:133)

因为您需要匹配内容而不将其包含在结果中(必须 匹配name="但它不是所需结果的一部分)某种形式的 需要零宽度匹配或组捕获。这可以做到 使用以下工具轻松完成:

的Perl

使用Perl,您可以使用n选项逐行循环并打印 捕获组的内容如果匹配:

perl -ne 'print "$1\n" if /name="(.*?)"/' filename

GNU grep

如果你有改进版的grep,比如GNU grep,你可能会有 -P选项可用。此选项将启用类似Perl的正则表达式, 允许你使用\K,这是一个速记的后视。它会重置 匹配位置,所以它之前的任何东西都是零宽度。

grep -Po 'name="\K.*?(?=")' filename

o选项使grep仅打印匹配的文本,而不是 整条线。

Vim - 文本编辑器

另一种方法是直接使用文本编辑器。与Vim,其中之一 实现这一目标的各种方法是删除没有的行 name=然后从结果行中提取内容:

:v/.*name="\v([^"]+).*/d|%s//\1

标准grep

如果您因某些原因无法访问这些工具 使用标准grep可以实现类似的功能。但是,没有看 周围需要进行一些清理:

grep -o 'name="[^"]*"' filename

关于保存结果的说明

在上述所有命令中,结果将发送至stdout。它的 重要的是要记住,你总是可以通过管道来保存它们 通过附加文件:

> result

到命令的末尾。

答案 1 :(得分:5)

正则表达式为:

.+name="([^"]+)"

然后分组将在\ 1

答案 2 :(得分:5)

如果您使用的是Perl,请下载一个模块来解析XML:XML::SimpleXML::TwigXML::LibXML。不要重新发明轮子。

答案 3 :(得分:4)

应该使用HTML解析器而不是正则表达式。一个利用HTML::TreeBuilder

的Perl程序

程序

#!/usr/bin/env perl

use strict;
use warnings;

use HTML::TreeBuilder;

my $tree = HTML::TreeBuilder->new_from_file( \*DATA );
my @elements = $tree->look_down(
    sub { defined $_[0]->attr('name') }
);

for (@elements) {
    print $_->attr('name'), "\n";
}

__DATA__
<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>

输出

content_analyzer
content_analyzer2
content_analyzer_items

答案 4 :(得分:2)

这可以做到:

perl -ne 'if(m/name="(.*?)"/){ print $1 . "\n"; }'

答案 5 :(得分:2)

这是一个使用HTML tidy&amp; amp; xmlstarlet:

htmlstr='
<table name="content_analyzer" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
<type="global" />
</table>
'

echo "$htmlstr" | tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null |
sed '/type="global"/d' |
xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v '@name' -n

答案 6 :(得分:1)

糟糕,sed命令当然必须在整齐的命令之前:

echo "$htmlstr" | 
sed '/type="global"/d' |
tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null |
xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v '@name' -n

答案 7 :(得分:0)

如果修复了xml(或一般文本)的结构,最简单的方法是使用cut。对于您的具体情况:

echo '<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>' | grep name= | cut -f2 -d '"'