(s)printf格式字符串的权威正则表达式

7
我希望能够回答这个问题并提供如下内容:
要想获得 Perl 所有的格式和哈希数据的键控访问,您需要一个(更好版本的)函数。以下是该函数的示例:this question
# sprintfx(FORMAT, HASHREF) - like sprintf(FORMAT, LIST) but accepts
# "%<key>$<tail>" instead of "%<index>$<tail>" in FORMAT to access the
# values of HASHREF according to <key>. Fancy formatting is done by
# passing '%<tail>', <corresponding value> to sprintf.
sub sprintfx {
  my ($f, $rh) = @_;
  $f =~ s/
     (%%)               # $1: '%%' for '%'
     |                  # OR
     %                  # start format
     (\w+)              # $2: a key to access the HASHREF
     \$                 # end key/index
     (                  # $3: a valid FORMAT tail
                        #   'everything' upto the type letter
        [^BDEFGOUXbcdefginosux]*
                        #   the type letter ('p' removed; no 'next' pos for storage)
         [BDEFGOUXbcdefginosux]
     )
    /$1 ? '%'                           # got '%%', replace with '%'
        : sprintf( '%' . $3, $rh->{$2}) # else, apply sprintf
    /xge;
  return $f;
}

但我为使用冒险/蛮力方法捕获格式字符串的“尾部”感到羞愧。

那么:有没有可以信任的FORMAT字符串的正则表达式?


你是否知道在sprintf中,%%不是一个特殊情况?例如,sprintf('%2%')将会产生字符串' %' - Ven'Tatsu
2个回答

1
如果您想了解如何像Perl一样精确地执行它,请参考Perl的操作方式。 Perl_sv_vcatpvfnsprintf格式解析器和评估器。(链接到5.14.2的实现。)

1

可接受的格式在perldoc -f sprintf中已经很好地规定了。在'%'和格式字母之间,您可以有:

     (\d+\$)?         # format parameter index (though this is probably
                      # incompatible with the dictionary feature)

     [ +0#-]*         # flags

     (\*?v)?          # vector flag

     \d*              # minimum width

     (\.\d+|\.\*)?    # precision or maximum width

     (ll|[lhqL])?     # size

问题在于某些修饰符仅适用于某些格式说明符。 - brian d foy
OP只是将格式令牌传递给内置函数sprintf,而不是尝试重新实现sprintf。如果输入包含无效的序列,它会被处理成与Perl的sprintf相同的方式处理,这可能是期望的行为。 - mob
sprintfx "%(abc)vs",{abc=>"def"}; 的输出应该是什么?它应该是 %(abc)vs 还是 %vs 也可以接受? - mob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接