2010-03-01 8 views
2

Dans PostgreSQL, il existe un type de données BLOB appelé bytea. C'est juste un tableau d'octets. sont émisregex pour correspondre à postgresql bytea

littéraux bytea de la manière suivante:

'\\037\\213\\010\\010\\005`Us\\000\\0001.fp3\'\\223\\222%' 

Voir PostgreSQL docs pour la définition complète du format.

J'essaye de construire un Perl regular expression qui correspondra à une telle chaîne.
Il devrait également correspondre littéraux standard chaîne SQL ANSI, comme 'Joe', 'Joe''s Mom', 'Fish Called ''Wendy'''
Il devrait également correspondre à la variante échappé antislash: 'Joe\'s Mom',.

La première approche (illustrée ci-dessous) ne fonctionne que pour certaines représentations bytea.

s{ '    # Opening apostrophe 
    (?:   # Start group 
     [^\\\'] # Anything but a backslash or an apostrophe 
    |    # or 
     \\ .  # Backslash and anything 
    |    # or 
     \'\'  # Double apostrophe 
    )*    # End of group 
    '    # Closing apostrophe 
}{LITERAL_REPLACED}xgo; 

Pour les autres (les plus longues, avec de nombreux se sont échappés apostrophes, Perl donne cet avertissement:

limite de récursion régulière complexe sous-expression (32766) a dépassé à la ligne 33 ./sqa.pl, <> ligne 1.

Je suis à la recherche d'un meilleur (mais toujours regex-base) solution, il faut probablement une alchimie regex (en évitant tout et des backreferences).

+1

Pourquoi ce wiki communautaire? – kennytm

+1

Pour commencer, placez [^ \\\ '] 'dans [^ \\'] +' pour qu'il puisse avancer plus d'un caractère à la fois dans le "cas habituel".(De plus cette troisième barre oblique inverse n'est pas nécessaire :) – hobbs

Répondre

0

tout d'abord, il semble que vous essayez de sorte que deux choses très différentes dans les deux expressions rationnelles:

  • apparier pour l'exactitude.
  • Ne le citez pas.

Pour correspondre, vous pouvez essayer quelque chose comme son:

m{^   # Start of string 
    '    # Opening apostrophe 
    (?>   # Start non-backtracking group 
     [^\\\'] # Anything but a backslash or an apostrophe 
    |    # or 
     (?:  # Start group 
      \d{3} #  3 digits 
      | 
      .  #  one other character 
     )   # end group 
    |    # or 
     ''   # Double apostrophe 
    )*    # End of group 
    '    # Closing apostrophe 
    $    # End of string 
}xms; 
+0

non Je ne vérifie pas l'exactitude. merci pour cette solution je vais le tester. – filiprem

+0

@Leon: Il vous manque le '\ 'dans ce cas. – kennytm

+0

@KennyTM: Oups. Accidentellement posté une version plus ancienne. Je l'ai réparé. –

1

OK, voici la meilleure solution que je pouvais mettre ensemble, grâce à Leon et hobbs.

Note: Ce n'est pas la solution que je recherchais! Il fait toujours échouer Perl avec l'avertissement "limite de récursivité (32766) dépassée", pour certaines chaînes longues. (essayez de placer 400k octets aléatoires dans un champ bytea, puis exportez avec pg_dump --inserts). Toutefois, il correspond à la plupart des chaînes bytea (telles qu'elles apparaissent dans le code SQL et dans les journaux de serveur) et aux chaînes de caractères SQL ANSI. Par exemple:

'\014cS\0059\036a4JEd\021o\005t\0015K7' 
'\\037\\213\\010\\010\\005`Us\\000\\0001.fp3\'\\223\\222%' 
' Joe''s Mom friend\'s dog is called \'Fluffy''' 

Et voici le regex:

m{ 
    '     # opening apostrophe 
    (?>     # start non-backtracking group 
     [^\\']+   # anything but a backslash or an apostrophe, one or more times 
    |     # or 
     (?:     # group of 
      \\ \\? [0-7]{3} # one or two backslashes and three octal digits 
     )+     # one or more times 
    |     # or 
     ''    # double apostrophe 
    |     # or 
     \\ [\\']  # backslash-escaped apostrophe or backslash 
    )*     # end of group 
    '     # closing apostrophe 
}x; 
1

Si vous ne se soucient pas de l'exactitude, au moins pour l'instant, vous ne pourriez pas juste essayer de faire correspondre les chaînes littérales régulièrement cités? Probablement quelque chose comme

m{ 
    (?>      # start of a quote group 
     '     # opening apostrophe 
     (?>     # start non-backtracking group 
      [^\\']+   # anything but a backslash or an apostrophe, one or more times 
     |     # or 
      \\ .   # backslash-escaped something 
     )*     # end of group 
     '     # closing apostrophe 
    )+      # end of a quote group, many of these 
}x; 
Questions connexes