postgres中的模式匹配9.1

时间:2015-02-12 21:39:19

标签: regex postgresql

我正在尝试提取相机制作&来自exifdata的模型。

exifdata本身很长,有4行:

JPEG.APP1.Ifd0.ImageDescription = ' '
JPEG.APP1.Ifd0.Make = 'Canon'
JPEG.APP1.Ifd0.Model = 'Canon PowerShot S120'
JPEG.APP1.Ifd0.Orientation = 1 = '0,0 is top left'

我使用以下正则表达式,但它们不匹配。模式是否正确?

    make := substring( meta from 'Make\\s+=\\s+(.*)');
    model := substring( meta from 'Model\\s+=\\s+(.*)');

1 个答案:

答案 0 :(得分:3)

subtring([str] from [pattern])不像您认为的那样有效。您可以在此处找到有关其工作原理的详细信息:9.7.2. SIMILAR TO Regular Expressions。这是您的调用使用的正则表达式语法。

对于初学者来说,有相关的信息:

  

SIMILAR TO一样,指定的模式必须与整个数据字符串匹配,否则函数将失败并返回null。

您的正则表达式显然与整个字符串不匹配。

第二句是下一句话:

  

要指示成功时应返回的模式部分,模式必须包含两次出现的转义字符,后跟双引号(“)

这不是标准的正则表达式,所以你需要注意它。

我不打算让subtring([str] from [pattern])工作,而是推荐替代方案:regexp_matches。此函数使用标准POSIX正则表达式语法,并返回包含匹配中所有捕获的组的text[]。这是一个快速测试,表明它有效:

SELECT regexp_matches($$JPEG.APP1.Ifd0.ImageDescription = ' '
JPEG.APP1.Ifd0.Make = 'Canon'
JPEG.APP1.Ifd0.Model = 'Canon PowerShot S120'
JPEG.APP1.Ifd0.Orientation = 1 = '0,0 is top left'$$, '(Make)') m;

(我正在使用dollar quoting作为示例字符串,以防您不熟悉该语法。)

这会返回数组{Make}

其次,正如我在测试中发现的那样,你的正则表达式实际上不起作用。你有两个问题:

  1. 双斜杠不正确。您不需要转义\,因为默认情况下PostgreSQL不会将其视为转义字符。你可以阅读有关字符串here中的转义的内容。最相关的部分可能是4.1.2.2. String Constants with C-style Escapes。该部分描述了您认为默认情况下发生的情况,但实际上需要E前缀才能启用。

    修复可以改善结果:

    SELECT regexp_matches($$JPEG.APP1.Ifd0.ImageDescription = ' '
    JPEG.APP1.Ifd0.Make = 'Canon'
    JPEG.APP1.Ifd0.Model = 'Canon PowerShot S120'
    JPEG.APP1.Ifd0.Orientation = 1 = '0,0 is top left'$$, 'Make\s+=\s+(.*)') m;
    

    现在给出一个包含这个字符串的数组:

    'Canon'
    JPEG.APP1.Ifd0.Model = 'Canon PowerShot S120'
    JPEG.APP1.Ifd0.Orientation = 1 = '0,0 is top left'
    

    这将我们带到......

  2. (.*)匹配字符串末尾的所有内容,而不是行尾。你可以通过做一些你可能想要做的事情来解决这个问题:从匹配中获取单引号。您可以使用此模式执行此操作:

    $$Make\s+=\s+'([^']+)'$$
    

    我再次使用美元报价,这次是为了避免逃避所有单引号的丑陋。现在查询是:

    SELECT regexp_matches($$JPEG.APP1.Ifd0.ImageDescription = ' '
    JPEG.APP1.Ifd0.Make = 'Canon'
    JPEG.APP1.Ifd0.Model = 'Canon PowerShot S120'
    JPEG.APP1.Ifd0.Orientation = 1 = '0,0 is top left'$$, $$Make\s+=\s+'([^']+)'$$) m;
    

    它几乎可以为您提供所需的内容:一个只包含字符串Canon的数组。当然,你需要从数组中提取结果,但我会把它作为练习留给你。

  3. 这应该足以让你获得第二个表达式。

    P.S。 PostgreSQL真正优秀的手册是一种祝福。