你能挽救我的负面回溯示例以实现数字化吗? [英] Can you salvage my negative lookbehind example for commifying numbers?

查看:69
本文介绍了你能挽救我的负面回溯示例以实现数字化吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

掌握 Perl 的高级正则表达式"一章中,我有一个坏的例子,我想不出一个好的解决办法.这个例子可能是为了自己的利益而试图过于聪明,但也许有人可以为我修复它.里面可能有这本书的免费副本,用于修复工作.:)

In the "Advanced Regular Expresssion" chapter in Mastering Perl, I have a broken example for which I can't figure out a nice fix. The example is perhaps trying to be too clever for its own good, but maybe someone can fix it for me. There could be a free copy of the book in it for working fixes. :)

在讨论环视的部分中,我想使用负向后视来为带有小数部分的数字实现一个 commifying 例程.关键是使用负面的回顾,因为那是主题.

In the section talking about lookarounds, I wanted to use a negative lookbehind to implement a commifying routine for numbers with fractional portions. The point was to use a negative lookbehind because that was the topic.

我愚蠢地这样做了:

$_ = '$1234.5678';
s/(?<!\.\d)(?<=\d)(?=(?:\d\d\d)+\b)/,/g;  # $1,234.5678

(?<!\.\d) 断言 (?=(?:\d\d\d)+\b) 不是小数点和数字.

The (?<!\.\d) asserts that the bit before the (?=(?:\d\d\d)+\b) is not a decimal point and a digit.

愚蠢的事情是不够努力去打破它.通过在末尾添加另一个数字,现在有一组三位数字前面没有小数点和一个数字:

The stupid thing is not trying hard enough to break it. By adding another digit to the end, there is now a group of three digits not preceded by a decimal point and a digit:

$_ = '$1234.56789';
s/(?<!\.\d)(?<=\d)(?=(?:\d\d\d)+\b)/,/g;  # $1,234.56,789

如果在 Perl 中lookbehinds 可以是可变宽度,这将非常容易.但他们不能.

If lookbehinds could be variable width in Perl, this would have been really easy. But they can't.

请注意,在没有负面回顾的情况下很容易做到这一点,但这不是示例的重点.有没有办法挽救这个例子?

Note that it's easy to do this without a negative lookbehind, but that's not the point of the example. Is there a way to salvage this example?

推荐答案

我认为没有某种形式的可变宽度后视是不可能的.在 5.10 中添加的 \K 断言提供了一种伪造可变宽度正向后视的方法.我们真正需要的是可变宽度的后视,但只要有一点创造力和很多丑陋,我们就可以让它发挥作用:

I don't think it's possible without some form of variable-width look-behind. The addition of the \K assertion in 5.10 provides a way of faking variable-width positive look-behind. What we really need is variable-width negative look-behind but with a little creativity and a lot of ugliness we can make it work:

use 5.010;
$_ = '$1234567890.123456789';
s/(?<!\.)(?:\b|\G)\d+?\K(?=(?:\d\d\d)+\b)/,/g;
say;  # $1,234,567,890.123456789

如果有一种模式需要 /x 符号,那就是这个:

If there was ever a pattern that begged for the /x notation it's this one:

s/
  (?<!\.)        # Negative look-behind assertion; we don't want to match
                 # digits that come after the decimal point.

  (?:            # Begin a non-capturing group; the contents anchor the \d
                 # which follows so that the assertion above is applied at
                 # the correct position.

    \b           # Either a word boundary (the beginning of the number)...

    |            # or (because \b won't match at subsequent positions where
                 # a comma should go)...

    \G           # the position where the previous match left off.

  )              # End anchor grouping

  \d+?           # One or more digits, non-greedily so the match proceeds
                 # from left to right. A greedy match would proceed from
                 # right to left, the \G above wouldn't work, and only the
                 # rightmost comma would get placed.

  \K             # Keep the preceding stuff; used to fake variable-width
                 # look-behind

                 # <- This is what we match! (i.e. a position, no text)

  (?=            # Begin a positive look-ahead assertion

    (?:\d\d\d)+  # A multiple of three digits (3, 6, 9, etc.)

    \b           # A word (digit) boundary to anchor the triples at the
                 # end of the number.

  )              # End positive look-ahead assertion.
/,/xg;

这篇关于你能挽救我的负面回溯示例以实现数字化吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆