【问题标题】:Perl regular expression help (parse out column)Perl 正则表达式帮助(解析列)
【发布时间】:2011-03-26 01:24:54
【问题描述】:

我被困在这里。不知道为什么我的 reg ex 不起作用。我有一个带有一系列列的管道分隔文本文件。我需要提取第三列。

文件:

A|B|C|D|E|F|G|H|I
2011-03-03 00:00:00.0|1|60510271|254735|27751|BBB|1|-0.1619023623|-0.009865904
2011-03-03 00:00:00.0|1|60510270|254735|27751|B|3|-0.0064786612|-0.0063739185
2011-03-03 00:00:00.0|1|60510269|254735|27751|B|3|-0.0084998226|-0.009244384

正则表达式:

$> head foo | perl -pi -e 's/^(.*)\|(.*)\|(.*)\|(.*)$/$3/g'

输出

-0.1619023623
-0.0064786612
-0.0084998226

显然输出的列不正确。

想法?

【问题讨论】:

  • 查看 Bllly 和 Gareth,了解您的正则表达式失败的原因。另外,括号里除了你喜欢挑出来的(第三个)就不用括号了,然后替换成$1 insread of $3

标签: regex perl


【解决方案1】:

通常,对于具有结构化分隔符的文件格式,不使用正则表达式更容易/更简单(KISS)。只需将字符串拆分为“|”分隔符并获取第三个字段。

awk -F"|" '{print $3}' file

使用 Ruby(1.9+)

ruby -F"\|" -ane 'puts $F[2]' file

使用 Perl,它类似于上面的 Ruby 单线。

perl -F"\|" -ane 'print $F[2]."\n"' file

【讨论】:

  • @Zaid,是的,我总是忘记-l 开关
【解决方案2】:

你需要让你的模式变得贪婪——所以:

's/^(.*?)\|(.*?)\|(.*?)\|(.*)$/$3/g'

【讨论】:

  • 或者不匹配这样的管道s/[^\|]+\|[^\|]+\|([^\|]+)\|/$1/g
  • 非常感谢。那行得通。我在 perl 脚本中使用它来解析 500,000 条记录。它不起作用,所以我使用 cmd 行中的 perl 来测试我所拍的 te 表达式。
【解决方案3】:

.* 默认情况下会尽可能匹配,因此您的 RE 会选择 last 三列(以及之前的所有内容)而不是 first 三列(以及之后的一切)。您可以通过(至少)两种方式避免这种情况:(1)而不是.*,寻找[^|]*,或(2)使您的重复运算符非贪婪:.*?而不是.*

(或者您可以显式拆分字符串,而不是使用单个 RE 匹配整个内容。您可能想尝试这两种方法,看看哪种方法性能更好,如果重要的话。拆分可能会提供更长但更清晰的代码。)

【讨论】:

    【解决方案4】:

    使用真正的解析器而不是破解一个正则表达式怎么样? Text::CSV 应该可以胜任。

    my $csv = Text::CSV->new({sep_char => "|"});
    

    【讨论】:

      【解决方案5】:

      首先想到的是 Text::CSV(由 Matt B 提到),但如果数据看起来像示例,我会说 split 是正确的选择。

      未经测试:

      $> head foo | perl -le 'while (<>) { print (split m{|})[2]; }'
      

      如果你真的想要一个正则表达式,我会使用这样的:

      s{^ [^\|]* \| [^\|]* \| ([^\|]*) \| .*$}{$1}gx;
      

      【讨论】:

        【解决方案6】:
        (?<=\|)\d{8}
        

        也许这会起作用 (?&lt;=\|) 积极寻找 | 字符后跟 8 位数字

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-05
          • 1970-01-01
          相关资源
          最近更新 更多