regex - Perl正则表达式解析SVG基本数据类型

标签 regex perl svg

我正在尝试收集验证 SVG 基本数据类型所需的所有 Perl 正则表达式。到目前为止我已经:

my $w        = "\\s*";
my $hexdigit = "[0-9A-Fa-f]";
my $c        = "$w,$w";
my $i        = "[0-9]+";
my $integer  = "[+-]?$i";
my $p        = "${i}%";
my $number   = "(?:$integer|[+-]?[0-9]*\.[0-9]+(?:[Ee]$integer)?)";
my $angle    = "(?:$number$w(?:deg|grad|rad)?)";
my $color    = "(?:#$hexdigit$hexdigit$hexdigit(?:$hexdigit$hexdigit$hexdigit)?|".
               "rgb\\($w$i$c$i$c$i$w\\)|".
               "rgb\\($w$p$c$p$c$p$w\\)|".
               '(?:'.join("|", sort keys %{svgColours()}). '))';
my $length     = "(?:$number(?:em|ex|px|in|cm|mm|pt|pc)?)";
my $coordinate = $length;
my $frequency  = "$number(?:Hz|kHz)";
my $FuncIRI    = "url\(.+\)";
my $numberOptionalNumber = "(?:$number|$number$c$number)"; 
my $paint      = "(?:fill|stroke)";
my $time       = "(?:$number(?:ms|s))";

如果您发现改进的机会,请告诉我。

最佳答案

您的想法是正确的(将内容拆分为可组合语法),但您这样做的方式有问题。

最重要的问题是许多反斜杠将被忽略。 "url\(.+\)"eq "url(.+)", "...\. ..." 不在句点前添加反斜杠。为了避免字符串和正则表达式的解析规则不同,我建议您使用正则表达式引号:qr//。这会产生编译所有这些正则表达式的副作用(您实际上并不想要),但至少您不必进行双重转义:

my $w = qr/\s*/;
...
my $paint = qr/fill|stroke/; # enclosing group added automatically

但是,这些模式中的每一个都必须作为正则表达式本身有意义。因此,您需要临时变量

my $color_names = join ...
my $color = qr/...|...|$color_names/;

将非正则表达式字符串连接在一起时,您应该养成转义所有元字符的习惯:

join '|', map quotemeta, keys %{ ... };

您可以使用 (?(DEFINE) ... ),而不是通过变量插值来编写正则表达式:

qr/
  (?(DEFINE)
    (?<ws>      \s* )
    (?<comma>   \s*[,]\s* )
    (?<integer> [+-]?[0-9]+ )
    (?<percent> (?&integer)[%] )
    (?<number>  (?&integer)(?: [.][0-9]+ (?: [eE](?&integer) )? )? )
    ...
  )
/x

DEFINE环境中,您可以将模式声明为命名捕获(但它们不捕获,并且您无法在此类模式内捕获)。您可以调用这样的模式,例如 (?&pattern)

如果您不仅想匹配数据,还想解析它,那么正则表达式可能不合适。我推荐 Marpa::R2 解析器。这是更底层的,表达能力较差,但具有很好的 BNF 语法:

:start   ::= NumberList
:default ::= action => ::array bless => ::lhs
:discard ~ ws

NumberList ::= number+ separator => comma

ws      ~ [\s]+
comma   ~ ','
digits  ~ [0-9]+
sign    ~ [+-]
integer ~ sign digits | digits
number  ~ integer
        | integer '.' digits
        | integer '.' digits [eE] integer
...

阅读Marpa documentation看看这个库是否有用。否则,Parse::RecDescentRegexp::Grammars是普通正则表达式的良好替代品。如果您选择基于正则表达式的解析器,则可以重用Regexp::Common中的常见模式。 .

关于regex - Perl正则表达式解析SVG基本数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18743629/

相关文章:

javascript - 如何将 svg 形状与 svg 文本合并

javascript - 从周围的 HTML 调用 SVG 内部的 JavaScript 函数

android - Kotlin正则表达式不适用于我在运行时得到的波兰char (“ł”)

java - Java 日期验证的正则表达式

perl - 使用perl构建关键字树

javascript - 无限水平地重复 SVG

c# - 使用正则表达式查找句子中的第一个单词

javascript - 正则表达式根据逗号分解字符串 ","

php - perl unary ~ 没有给出预期的结果

perl - 在 Perl 中从括号中获取键值对