Gestion des expressions régulières par PHP / Python

Gérer les expressions régulières en PHP / Python

Je voulais résumer les preg_xxx et les expressions régulières qui sont utilisées relativement lors du développement avec PHP sous forme de mémorandum, alors je les ai écrites ici. En fin de compte, tous sont modifiés et utilisés au besoin, mais ils sont utilisés comme une base raisonnable. Il décrit également si des résultats similaires peuvent être obtenus avec Python3.

Exemple utilisant PHP preg_match

Date et l'heure

Cela doit encore être examiné, mais comme exemple d'expression régulière. Il est modifié à chaque fois en fonction du cas d'entrée et de l'utilisation.

Expressions régulières

/\A(\d{4})*[-\/]*(\d{1,2})[-\/]*(\d{1,2}) *((\d{1,2}):(\d{1,2})(:(\d{1,2}))*)*\Z/

Notation sens
/ délimiteur
\A Le début de la chaîne
() Traiter comme un ensemble
\d{4} Numéro à 4 chiffres
* Répétez 0 fois ou plus du motif précédent
[] Jeu de caractères,[]L'un des personnages de
\d{1,2} Valeur numérique de 1 à 2 chiffres
\Z La fin de la chaîne

Code et résultats

Pour PHP
<?php

function pick_date(string $date) :array {
    if (preg_match('/\A(\d{4})*[-\/]*(\d{1,2})[-\/]*(\d{1,2}) *((\d{1,2}):(\d{1,2})(:(\d{1,2}))*)*\Z/', $date, $matches)) {
        return [
            'Y' => isset($matches[1]) ?intval($matches[1]) : -1,
            'm' => isset($matches[2]) ?intval($matches[2]) : -1,
            'd' => isset($matches[3]) ?intval($matches[3]) : -1,
            'H' => isset($matches[5]) ?intval($matches[5]) : -1,
            'i' => isset($matches[6]) ?intval($matches[6]) : -1,
            's' => isset($matches[8]) ?intval($matches[8]) : -1
        ];
    } else {
        return [];
    }
}

print_r(pick_date('2017-07-03 13:15:03'));
print_r(pick_date('2017-07-3 13:01'));
print_r(pick_date('2017/07/03 13'));
print_r(pick_date('2017/07-3 13:1:3'));
print_r(pick_date('201773 13:00'));

Résultat d'exécution


Array
(
    [Y] => 2017
    [m] => 7
    [d] => 3
    [H] => 13
    [i] => 15
    [s] => 3
)
Array
(
    [Y] => 2017
    [m] => 7
    [d] => 3
    [H] => 13
    [i] => 1
    [s] => -1
)
Array
(
)
Array
(
    [Y] => 2017
    [m] => 7
    [d] => 3
    [H] => 13
    [i] => 1
    [s] => 3
)
Array
(
    [Y] => 2017
    [m] => 7
    [d] => 3
    [H] => 13
    [i] => 0
    [s] => -1
)
Pour Python 3

Contrairement à PHP, aucune délimitation n'est requise. De plus, si vous n'êtes pas au courant de la commande, vous pouvez utiliser dict au lieu de ʻOrderedDict. Vous pouvez obtenir le même résultat de sortie que PHP avec findall`.

import re
from collections import OrderedDict


def pick_date(date):
    pattern = r'\A(\d{4})*[-\/]*(\d{1,2})[-\/]*(\d{1,2}) *((\d{1,2}):(\d{1,2})(:(\d{1,2}))*)*\Z'
    match = re.findall(pattern, date)
    try:
        elements = match[0]
        return OrderedDict((
            ('Y', elements[0]),
            ('m', elements[1]),
            ('d', elements[2]),
            ('H', elements[4]),
            ('i', elements[5]),
            ('s', elements[7])
        ))
    except IndexError:
        return OrderedDict()

print(pick_date('2017-07-03 13:15:03'))
print(pick_date('2017-07-3 13:01'))
print(pick_date('2017/07/03 13'))
print(pick_date('2017/07-3 13:1:3'))
print(pick_date('201773 13:00'))

Résultat de sortie


OrderedDict([('Y', '2017'), ('m', '07'), ('d', '03'), ('H', '13'), ('i', '15'), ('s', '03')])
OrderedDict([('Y', '2017'), ('m', '07'), ('d', '3'), ('H', '13'), ('i', '01'), ('s', '')])
OrderedDict()
OrderedDict([('Y', '2017'), ('m', '07'), ('d', '3'), ('H', '13'), ('i', '1'), ('s', '3')])
OrderedDict([('Y', '2017'), ('m', '7'), ('d', '3'), ('H', '13'), ('i', '00'), ('s', '')])

Remarques

Dans ce cas, selon le scénario, la méthode suivante peut être meilleure sans utiliser d'expressions régulières. Sera-ce ici si c'est strict?

Pour PHP
<?php

date_default_timezone_set('Asia/Tokyo');

function pick_date(string $date) : array {
    $dt = new DateTime();

    return [
        'y' => $dt->setTimestamp(strtotime($date))->format('Y'),
        'm' => $dt->format('m'),
        'd' => $dt->format('d'),
        'H' => $dt->format('H'),
        'i' => $dt->format('i'),
        's' => $dt->format('s'),
    ];
}

print_r(pick_date('2017-07-03 13:15:03'));
print_r(pick_date('2017-07-3 13:01'));
print_r(pick_date('2017/07/03 13'));
print_r(pick_date('2017/07-3 13:1:3'));
print_r(pick_date('201773 13:00'));

Résultat de sortie


Array
(
    [y] => 2017
    [m] => 07
    [d] => 03
    [H] => 13
    [i] => 15
    [s] => 03
)
Array
(
    [y] => 2017
    [m] => 07
    [d] => 03
    [H] => 13
    [i] => 01
    [s] => 00
)
Array
(
    [y] => 1970
    [m] => 01
    [d] => 01
    [H] => 09
    [i] => 00
    [s] => 00
)
Array
(
    [y] => 1970
    [m] => 01
    [d] => 01
    [H] => 09
    [i] => 00
    [s] => 00
)
Array
(
    [y] => 1970
    [m] => 01
    [d] => 01
    [H] => 09
    [i] => 00
    [s] => 00
)
Pour Python 3

J'ai réfléchi à la façon de convertir une fois avec strptime de datetime, mais contrairement à strtotime de PHP, il est nécessaire de spécifier format, donc je ne peux pas faire quelque chose de similaire.

Validation du format d'e-mail

Vérifiez s'il est conforme au format de l'e-mail. Voir ici pour référence.

Expressions régulières

/\A^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$\Z/

Notation sens
/ délimiteur
\A Le début de la chaîne
[1] []Commence par l'un des caractères (jeu de caractères) dans
a-z Caractères de a à z
() Traiter comme un ensemble
+ Une ou plusieurs répétitions du modèle précédent
\. Point(".") S'échapper pour déterminer
* Répétez 0 fois ou plus du motif précédent
[a-z]{2,} Deux lettres minuscules ou plus
\Z La fin de la chaîne

Code et résultats

Pour PHP
<?php

function validate_email_format(string $email) : int {
    return preg_match('/\A^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$\Z/', $email);
}

print(validate_email_format('[email protected]'). PHP_EOL);
print(validate_email_format('[email protected]'). PHP_EOL);
print(validate_email_format('[email protected]'). PHP_EOL);
print(validate_email_format('[email protected]'). PHP_EOL);
print(validate_email_format('test@testcom'). PHP_EOL);

Résultat de sortie


1
0
0
0
0
Pour Python 3
import re


def validate_email_format(email):
    pattern = r'\A^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$\Z'
    return 1 if re.match(pattern, email) else 0

print(validate_email_format('[email protected]'))
print(validate_email_format('[email protected]'))
print(validate_email_format('[email protected]'))
print(validate_email_format('[email protected]'))
print(validate_email_format('test@testcom'))

Résultat de sortie


1
0
0
0
0

Validation du format d'URL

Validez s'il est conforme au format de l'URL (dans ce cas, considérez également ftp). J'ai fait référence à ici.

Expressions régulières

/^(https?|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?([0-9]+)?\/?/i

Notation sens
/ délimiteur
() Ensemble d'expressions,
^() Commence par un ensemble d'expressions
? Avec ou sans le motif précédent
| Signification de OR
[] Jeu de caractères,[]L'un des personnages de
(?:) Ne pas capturer
+ Une ou plusieurs répétitions du modèle précédent
* Répétez 0 fois ou plus du motif précédent
i Insensible à la casse

Code et résultats

Pour PHP
<?php

function pick_url(string $url) : array {
    if (preg_match('/^(https?|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?([0-9]+)?\/?/i', $url, $matches)) {
        return [
            $matches[0] ?? "",
            $matches[1] ?? ""
        ];
    } else {
        return ["", ""];
    }
}

print_r(pick_url('http://test.xxx?a=b'));
print_r(pick_url('https://test.xxx/a/b/'));
print_r(pick_url('ftp://test.xxx'));
print_r(pick_url('ftps://test.xxx'));
print_r(pick_url('https:///test.xxx'));

Résultat de sortie


Array
(
    [0] => http://test.xxx
    [1] => http
)
Array
(
    [0] => https://test.xxx/
    [1] => https
)
Array
(
    [0] => ftp://test.xxx
    [1] => ftp
)
Array
(
    [0] =>
    [1] =>
)
Array
(
    [0] =>
    [1] =>
)
Pour Python 3
import re


def pick_url(url):
    pattern = r'^(https?|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?([0-9]+)?\/?'
    match = re.compile(pattern, re.IGNORECASE).findall(url)
    try:
        elements = match[0]
        return [elements[0], elements[1]]
    except IndexError:
        return ["", ""]

print(pick_url('http://test.xxx?a=b'))
print(pick_url('https://test.xxx/a/b/'))
print(pick_url('ftp://test.xxx'))
print(pick_url('ftps://test.xxx'))
print(pick_url('https:///test.xxx'))

Résultat de sortie


['http', 'test.xxx']
['https', 'test.xxx']
['ftp', 'test.xxx']
['', '']
['', '']

Exemple utilisant PHP preg_replace

Remplacement de mot

Dans cet exemple, un exemple qui remplace le mot «abc» par «ABC». A cette époque, j'ai eu une expérience difficile avec la façon de réécrire mot par mot, alors prenez note. En fait, ce n'est pas non plus strict, je le change donc d'un cas à l'autre.

Expressions régulières

/(\b)(abc)(\b)/

Notation sens
/ délimiteur
() Ensemble d'expressions
\b Correspond aux caractères qui bordent les mots anglais

Code et résultats

Pour PHP
<?php

function replace_abc(string $s) : string {
    return preg_replace('/(\b)(abc)(\b)/', '${1}ABC${3}', $s);
}

print(replace_abc('abcd abc" dabcd abc'). "\n");
print(replace_abc('abc dabc abc d "abc"'). "\n");
print(replace_abc('abcd +abc" abc abc?'). "\n");
print(replace_abc('a!abc \'abc\' sabcs abc\'s!'). "\n");
print(replace_abc('ababc? \'abc?\' sabcs abc!?'). "\n");

Résultat de sortie


abcd ABC" dabcd ABC
ABC dabc ABC d "ABC"
abcd +ABC" ABC ABC?
a!ABC 'ABC' sabcs ABC's!
ababc? 'ABC?' sabcs ABC!?
Pour Python 3

Aucune délimitation n'est requise comme PHP. De plus, la méthode de spécification du format après le remplacement est décrite comme «\ 1» au lieu de «$ {1}».

import re


def replace_abc(s):
    return re.sub(r'(\b)(abc)(\b)', r'\1ABC\3', s)

print(replace_abc('abcd abc" dabcd abc'))
print(replace_abc('abc dabc abc d "abc"'))
print(replace_abc('abcd +abc" abc abc?'))
print(replace_abc('a!abc \'abc\' sabcs abc\'s!'))
print(replace_abc('ababc? \'abc?\' sabcs abc!?'))

Résultat de sortie


abcd ABC" dabcd ABC
ABC dabc ABC d "ABC"
abcd +ABC" ABC ABC?
a!ABC 'ABC' sabcs ABC's!
ababc? 'ABC?' sabcs ABC!?

Exemple utilisant preg_replace_callback et preg_split de PHP

fichier csv

Supposons que vous souhaitiez obtenir une colonne csv contenant des guillemets doubles comme celui ci-dessous.

test.csv


a,b,c
"a,b","b,c","c,d"
"a,b,\"a,b\",,c","a,,b,,",c
"a,,","a,b,\"a,b,c\",c,d,","a\"a,b\",c"

Résultat attendu (()Est décrit pour une identification facile)


(a), (b), (c)
(a,b), (b,c), (c,d)
(a,b,\"a,b\",,c), (a,,b,,), (c)
(a,,), (a,b,\"a,b,c\",c,d,), (a\"a,b\",c)

Comment ne pas utiliser d'expressions régulières

Pour PHP

Cela ne fonctionne pas s'il y a un guillemet double dans le guillemet double. Il y a peut-être un moyen, mais ici, nous utilisons des expressions régulières. Dans cette méthode, est-ce une image qui est extraite par preg_split ('/, (?!") /', $ Columns); ? Lorsque j'ai examiné ces questions, il y avait de nombreuses façons de les extraire par programmation. Réalisons-le avec une expression régulière.

csv.php


<?php

$file = fopen("test.csv", "r");

if ($file) {
    while (($columns = fgetcsv($file, 0, ',', '"', '"')) !== FALSE) {
        print_r($columns);
    }
}

fclose($file);

Résultat de sortie


Array
(
    [0] => a
    [1] => b
    [2] => c

)
Array
(
    [0] => "a
    [1] => b","b
    [2] => c","c
    [3] => d"

)
Array
(
    [0] => "a
    [1] => b
    [2] => \"a
    [3] => b\"
    [4] =>
    [5] => c","a
    [6] =>
    [7] => b
    [8] => ,"
    [9] => c

)
Array
(
    [0] => "a
    [1] => ,","a
    [2] => b
    [3] => \"a
    [4] => b
    [5] => c\"
    [6] => c
    [7] => d,","a\"a
    [8] => b\"
    [9] => c"
)
Pour Python 3

Cela semble assez précis. L'exemple test.csv semble un peu trop agressif, mais je ne peux rien dire car j'ai en fait rencontré un csv similaire.

import csv

with open('test.csv') as f:
    r = csv.reader(f)
    for column in r:
        print(column)

Résultat de sortie


['a', 'b', 'c']
['a,b', 'b,c', 'c,d']
['a,b,\\a', 'b\\"', '', 'c"', 'a,,b,,', 'c']
['a,,', 'a,b,\\a', 'b', 'c\\"', 'c', 'd', ',a\\"a', 'b\\"', 'c"']

Modèles utilisant des expressions régulières

Expressions régulières

/(?:\n|\r|\r\n)/

Notation sens
/ délimiteur
() Ensemble d'expressions,
(?:) Ne pas capturer
| Signification de OR
[] Jeu de caractères,[]L'un des personnages de
+ Une ou plusieurs répétitions du modèle précédent
Code et résultats
Pour PHP
<?php

function my_generator(string $name) : Iterator {
    $from = function () use ($name) {
        $file = fopen($name, "r");

        if ($file) {
            while ($line = fgets($file)) {
                yield $line;
            }
        }
        fclose($file);
    };

    yield from $from();
}

$pattern = '/\"(?:\\\"|[^\"])+\"/';
$bks = [];
foreach (my_generator("test.csv") as $v) {
    // "Stockez la valeur incluse et remplacez-la par un identifiant unique
    $columns = preg_replace_callback($pattern, function ($matches) use (&$bk) {
        $index = uniqid();
        $bk[$index] = $matches[0];
        return $index;
    }, $v);
    //Supprimer le code de saut de ligne
    $columns = preg_split('/,/', preg_replace("/\r|\n/", "", $columns));
    //Restaurer la valeur remplacée par id
    $new_columns = array_map(function ($column) use ($bk) {
        if (!empty($bk) && array_key_exists($column, $bk)) {
            return $bk[$column];
        } else {
            return $column;
        }
    }, $columns);
    print_r($new_columns);
}

Résultat de sortie


Array
(
    [0] => a
    [1] => b
    [2] => c
)
Array
(
    [0] => "a,b"
    [1] => "b,c"
    [2] => "c,d"
)
Array
(
    [0] => "a,b,\"a,b\",,c"
    [1] => "a,,b,,"
    [2] => c
)
Array
(
    [0] => "a,,"
    [1] => "a,b,\"a,b,c\",c,d,"
    [2] => "a\"a,b\",c"
)
Pour Python 3
import re
import uuid

bks = {}


def my_generator():
    with open('test.csv') as lines:
        yield from lines


def repl(m):
    index = str(uuid.uuid4())
    bks[index] = m.group(0)
    return index

pattern = r'\"(?:\\\"|[^\"])+\"'
for k, v in enumerate(my_generator()):
    columns = re.sub(pattern, repl, v).rstrip('\r\n').split(",")
    new_columns = []
    for c in columns:
        if c in bks:
            new_columns.append(bks[c])
        else:
            new_columns.append(c)
    print(new_columns)

Résultat de sortie


['a', 'b', 'c']
['"a,b"', '"b,c"', '"c,d"']
['"a,b,\\"a,b\\",,c"', '"a,,b,,"', 'c']
['"a,,"', '"a,b,\\"a,b,c\\",c,d,"', '"a\\"a,b\\",c"']

Remarques

Il semble qu'il existe des cas où les guillemets doubles dans les guillemets doubles ne sont pas échappés. Je voudrais essayer un code qui peut gérer des notations telles que "" "a, b", c "," a, b, "a", "b" ", c`.


  1. ↩︎

Recommended Posts

Gestion des expressions régulières par PHP / Python
[Python] Expressions régulières Expressions régulières
Remplacer non-ASCII par des expressions régulières en Python
Python: analyse morphologique simplifiée avec des expressions régulières
Manipuler yaml avec python
[Python] Débarrassez-vous de la datation avec des expressions régulières
Extraire des nombres avec des expressions régulières
Manipulation d'expressions régulières par Python
À propos de Python et des expressions régulières
Proxy dynamique avec python, ruby, PHP
Je ne me souviens pas des expressions régulières Python
Remplacement de chaîne par une expression régulière Python
Envoyer l'image avec python et enregistrer avec php
Lors de l'utilisation d'expressions régulières en Python
Chevauchement d'expressions régulières en Python et Java
Réaliser un générateur PHP / Python avec Golang / Ruby
N'utilisez pas \ d dans les expressions régulières Python 3!
Statistiques avec python
Python avec Go
Twilio avec Python
Intégrer avec Python
Jouez avec 2016-Python
AES256 avec python
Testé avec Python
Gestion des erreurs Python
Gestion des exceptions Python
python commence par ()
avec syntaxe (Python)
Bingo avec python
Gestion des fuseaux horaires Python
Zundokokiyoshi avec python
Excel avec Python
Gestion des exceptions Python
Micro-ordinateur avec Python
Cast avec python
Distinguer les chiffres et les lettres avec des expressions régulières
Un chercheur d'une société pharmaceutique a résumé les expressions canoniques en Python
Pandas Python: recherchez DataFrame à l'aide d'expressions régulières
J'ai essayé d'utiliser mecab avec python2.7, ruby2.3, php7
Une histoire sur la gestion des données binaires en Python
Supprimer les chaînes supplémentaires dans l'URL avec une expression canonique
Combinez des chaînes répétitives en une seule avec des expressions régulières Python.
Zip, décompressez avec python
Django 1.11 a démarré avec Python3.6
Jugement des nombres premiers avec Python
Python avec eclipse + PyDev.
Grattage en Python (préparation)
Essayez de gratter avec Python.
Apprendre Python avec ChemTHEATER 03
Recherche séquentielle avec Python
"Orienté objet" appris avec python
Exécutez Python avec VBA
Communication série avec python
Apprendre Python avec ChemTHEATER 05-1
Apprenez Python avec ChemTHEATER
Scraping avec Python, publication sur TwitterBot, exécution régulière sur Heroku
Exécutez prepDE.py avec python3
1.1 Premiers pas avec Python
Collecter des tweets avec Python
Binarisation avec OpenCV / Python