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.
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.
/\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 |
<?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
)
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', '')])
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?
<?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
)
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.
Vérifiez s'il est conforme au format de l'e-mail. Voir ici pour référence.
/\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 |
<?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
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
Validez s'il est conforme au format de l'URL (dans ce cas, considérez également ftp
). J'ai fait référence à ici.
/^(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 |
<?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] =>
)
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']
['', '']
['', '']
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.
/(\b)(abc)(\b)/
Notation | sens |
---|---|
/ | délimiteur |
() | Ensemble d'expressions |
\b | Correspond aux caractères qui bordent les mots anglais |
<?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!?
$ {N}
dans '$ {1} ABC $ {3}' '
signifie le nième caractère correspondant.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!?
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)
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"
)
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"']
/(?:\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 |
(?:)
sur,$str = preg_replace('/(?:\n|\r|\r\n)/', '', $str);
Il peut également être utilisé lors de la suppression de codes de saut de ligne tels que<?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"
)
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"']
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`.
Recommended Posts