« Hacks en perl » : différence entre les versions

De knowledge
Aller à la navigation Aller à la recherche
mAucun résumé des modifications
mAucun résumé des modifications
 
Ligne 22 : Ligne 22 :
   (?{ [$^R, {}] })
   (?{ [$^R, {}] })
   \{
   \{
     (?: (?&KV) # [[$^R, {}], $k, $v]
     (?: \s* (?&KV)
       (?{ # warn Dumper { obj1 => $^R };
       (?{
[$^R->[0][0], {$^R->[1] => $^R->[2]}] })
        [$^R->[0][0], { $^R->[1] => $^R->[2] }]
       (?: , (?&KV) # [[$^R, {...}], $k, $v]
      })
         (?{ # warn Dumper { obj2 => $^R };
       (?: \s*,\s* (?&KV)
  [$^R->[0][0], {%{$^R->[0][1]}, $^R->[1] => $^R->[2]}] })
         (?{
          [$^R->[0][0], { %{$^R->[0][1]}, $^R->[1] => $^R->[2] }]
        })
       )*
       )*
     )?
     )?
Ligne 34 : Ligne 36 :


(?<KV>
(?<KV>
   (?&STRING) # [$^R, "string"]
   (?&STRING) \s* : \s* (?&VALUE)
  : (?&VALUE) # [[$^R, "string"], $value]
   (?{ # warn Dumper { kv => $^R };
   (?{ # warn Dumper { kv => $^R };
     [$^R->[0][0], $^R->[0][1], $^R->[1]] })
     [$^R->[0][0], $^R->[0][1], $^R->[1]] })
Ligne 43 : Ligne 44 :
   (?{ [$^R, []] })
   (?{ [$^R, []] })
   \[
   \[
     (?: (?&VALUE) (?{ [$^R->[0][0], [$^R->[1]]] })
     (?: \s* (?&VALUE)
       (?: , (?&VALUE) (?{ # warn Dumper { atwo => $^R };
      (?{ [$^R->[0][0], [$^R->[1]]] })
[$^R->[0][0], [@{$^R->[0][1]}, $^R->[1]]] })
       (?: \s*,\s* (?&VALUE)
        (?{ # warn Dumper { atwo => $^R };
          [$^R->[0][0], [@{$^R->[0][1]}, $^R->[1]]] })
       )*
       )*
     )?
     )?
   \]
   \s* \]
)
)
(?<VALUE>
(?<VALUE>
   \s*
   \s*
Ligne 78 : Ligne 80 :
     |
     |
       \\ ["\\/bfnrt]
       \\ ["\\/bfnrt]
#    |
#      \\ u [0-9a-fA-f]{4}
     )*
     )*
     "
     "
Ligne 114 : Ligne 114 :




 
                                                                                                                                                                                                                                                         
</syntaxhighlight>La fonction from_json() accepte une chaine (la "phrase" JSON) et renvoie un objet perl reflétant la structure de la "phrase" JSON.
</syntaxhighlight>La fonction from_json() accepte une chaine (la "phrase" JSON) et renvoie un objet perl reflétant la structure de la "phrase" JSON.
Attention c'est assez sensible aux espaces. L'objet JSON <code>{"nom":"Jean PINON", "taille": 175}</code> va provoquer une erreur alors que  <code>{"nom":"Jean PINON","taille":175}</code> marche parfaitement. <syntaxhighlight lang="text">
$ ./json.pl
{"nom":"Jean Pinon", "age": 15}
$VAR1 = 'no match';
{"nom":"Jean Pinon","age":15}
$VAR1 = {
          'age' => 15,
          'nom' => 'Jean Pinon'
        };
</syntaxhighlight>Je penses que la regexp est corrigible mais... j'ai pas encore le courage!

Version actuelle datée du 9 octobre 2025 à 07:23

Perl est merveilleux puissant mais... pas très clair. Je vais poser ici quelques hacks perl qui vous feront passer pour des pros.

JSON vers PERL

Il y a un module perl pour cela. Le module JSON.

use JSON;

Un lien est donné dans metacpan. mais c'est lourd et, parfois on n'a pas la place de l'installer. C'est notamment le cas pour les mini modules GLINET sous OpenWRT.

Ici on parle de méthodes "roots" qui marchent sans aucun modules.

On utilise des expressions rationnelles (regexp) :

#!/usr/bin/env perl

use Data::Dumper qw(Dumper);

my $FROM_JSON = qr{

(?&VALUE) (?{ $_ = $^R->[1] })

(?(DEFINE)

(?<OBJECT>
  (?{ [$^R, {}] })
  \{
    (?: \s* (?&KV)
      (?{
        [$^R->[0][0], { $^R->[1] => $^R->[2] }]
      })
      (?: \s*,\s* (?&KV)
        (?{
          [$^R->[0][0], { %{$^R->[0][1]}, $^R->[1] => $^R->[2] }]
        })
      )*
    )?
  \}
)

(?<KV>
  (?&STRING) \s* : \s* (?&VALUE)
  (?{ # warn Dumper { kv => $^R };
     [$^R->[0][0], $^R->[0][1], $^R->[1]] })
)

(?<ARRAY>
  (?{ [$^R, []] })
  \[
    (?: \s* (?&VALUE)
      (?{ [$^R->[0][0], [$^R->[1]]] })
      (?: \s*,\s* (?&VALUE)
        (?{ # warn Dumper { atwo => $^R };
           [$^R->[0][0], [@{$^R->[0][1]}, $^R->[1]]] })
      )*
    )?
  \s* \]
)
(?<VALUE>
  \s*
  (
      (?&STRING)
    |
      (?&NUMBER)
    |
      (?&OBJECT)
    |
      (?&ARRAY)
    |
    true (?{ [$^R, 1] })
  |
    false (?{ [$^R, 0] })
  |
    null (?{ [$^R, undef] })
  )
  \s*
)

(?<STRING>
  (
    "
    (?:
      [^\\"]+
    |
      \\ ["\\/bfnrt]
    )*
    "
  )

  (?{ [$^R, eval $^N] })
)

(?<NUMBER>
  (
    -?
    (?: 0 | [1-9]\d* )
    (?: \. \d+ )?
    (?: [eE] [-+]? \d+ )?
  )

  (?{ [$^R, eval $^N] })
)

) }xms;

sub from_json {
  local $_ = shift;
  local $^R;
  eval { m{\A$FROM_JSON\z}; } and return $_;
  die $@ if $@;
  return 'no match';
}

while (<>) {
  chomp;
  print Dumper from_json($_);
}

La fonction from_json() accepte une chaine (la "phrase" JSON) et renvoie un objet perl reflétant la structure de la "phrase" JSON.