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

wra*_*ler 81 regex perl text-extraction sed html-parsing

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

    <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>
Run Code Online (Sandbox Code Playgroud)

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

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

sid*_*yll 147

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

Perl的

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

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

GNU grep

如果你有一个改进的grep版本,比如GNU grep,你可以 -P选择它.此选项将启用类似Perl的正则表达式,允许您使用\K哪个是速记外观.它将重置匹配位置,因此它之前的任何内容都是零宽度.

grep -Po 'name="\K.*?(?=")' filename
Run Code Online (Sandbox Code Playgroud)

o 选项使grep仅打印匹配的文本,而不是整行.

Vim - 文本编辑器

另一种方法是直接使用文本编辑器.使用Vim,完成此操作的各种方法之一是删除行 name=,然后从结果行中提取内容:

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

标准grep

如果您无法访问这些工具,出于某种原因,可以使用标准grep实现类似的功能.但是,如果不浏览它,将需要稍后进行一些清理:

grep -o 'name="[^"]*"' filename
Run Code Online (Sandbox Code Playgroud)

关于保存结果的说明

在上面的所有命令中,结果将被发送到stdout.重要的是要记住,您可以通过附加以下内容将它们连接到文件来保存它们:

> result
Run Code Online (Sandbox Code Playgroud)

到命令的末尾.

  • Lookarounds(在GNU`grep`中):`grep -Po'.*name ="\ K.*?(?=".*)'` (11认同)
  • 我为什么要生气?没有`.*`,你可以做`grep -Po'(?<= name =").*?(?=")'`.`\ K`可用于速记,但只有当左边的匹配是可变长度时才需要它.在这种情况下,使用外观的原因是相当明显的.Ungreedy操作看起来有点整洁(`[^"]*`与`.*?`并且你不必重复锚字符.我不知道速度.这在很大程度上取决于环境,我认为我希望这很有帮助. (2认同)

Mat*_*ver 5

正则表达式将是:

.+name="([^"]+)"
Run Code Online (Sandbox Code Playgroud)

然后分组将在\ 1中


sha*_*rey 5

如果您正在使用Perl,请下载一个模块来解析XML:XML :: Simple,XML :: TwigXML :: LibXML.不要重新发明轮子.

  • 请注意,OP给出的示例格式不正确(例如`<type ="global"`),因此大多数XML解析器都会抱怨并死掉. (3认同)

Ala*_*avi 5

为此,应使用HTML解析器而不是正则表达式。使用以下内容的Perl程序HTML::TreeBuilder

程序

#!/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>
Run Code Online (Sandbox Code Playgroud)

输出量

content_analyzer
content_analyzer2
content_analyzer_items
Run Code Online (Sandbox Code Playgroud)