PHP preg_split se parentesi graffe non all'interno
-
20-09-2019 - |
Domanda
Sono makin' un interprete del linguaggio di scripting PHP. Ho questo codice in linguaggio di scripting che:
write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly
(Sì, è difficile da credere, ma che è la sintassi)
Quali regex devo usare per dividere questo (split da spazi), ma solo se non all'interno delle parentesi graffe. Quindi voglio girare il codice sopra in questo array:
- scrittura
- Ciao, mondo!
- in
- o
- il
- color
- blu
- o
- rossa
- o
- # 00AA00
- e
- in
- o
- il
- carattere
- Arial Black
- o
- Monaco
- dove
- sia
- il
- color
- e
- carattere
- sono
- determinato
- in modo casuale
(Le stringhe all'interno delle parentesi graffe sono esposizione qui sopra in grassetto ) Le stringhe all'interno delle parentesi graffe devono essere un elemento ciascuno. Così {! Ciao, Mondo} non può essere: 1. Ciao, 2. World!
Come posso fare questo?
Grazie in anticipo.
Soluzione
Cosa succede ad usare qualcosa di simile a questo:
$str = 'write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly';
$matches = array();
preg_match_all('#\{.*?\}|[^ ]+#', $str, $matches);
var_dump($matches[0]);
che vi consentiranno di:
array
0 => string 'write' (length=5)
1 => string '{Hello, World!}' (length=15)
2 => string 'in' (length=2)
3 => string 'either' (length=6)
4 => string 'the' (length=3)
5 => string 'color' (length=5)
6 => string '{blue}' (length=6)
7 => string 'or' (length=2)
8 => string '{red}' (length=5)
9 => string 'or' (length=2)
10 => string '{#00AA00}' (length=9)
11 => string 'and' (length=3)
12 => string 'in' (length=2)
13 => string 'either' (length=6)
14 => string 'the' (length=3)
15 => string 'font' (length=4)
16 => string '{Arial Black}' (length=13)
17 => string 'or' (length=2)
18 => string '{Monaco}' (length=8)
19 => string 'where' (length=5)
20 => string 'both' (length=4)
21 => string 'the' (length=3)
22 => string 'color' (length=5)
23 => string 'and' (length=3)
24 => string 'the' (length=3)
25 => string 'font' (length=4)
26 => string 'are' (length=3)
27 => string 'determined' (length=10)
28 => string 'randomly' (length=8)
Il, è sufficiente iterare su tali risultati; quelli a partire da {e terminano da} saranno le tue parole "importanti", e gli altri saranno il resto.
Modifica al termine il commento: un modo per identificare le parole importanti sarebbe qualcosa di simile:
foreach ($matches[0] as $word) {
$m = array();
if (preg_match('#^\{(.*)\}$#', $word, $m)) {
echo '<strong>' . htmlspecialchars($m[1]) . '</strong>';
} else {
echo htmlspecialchars($word);
}
echo '<br />';
}
In alternativa, come hai detto tu, lavorando con strpos e strlen avrebbe funzionato troppo; -)
Altri suggerimenti
Ha l'ordine importa? Se non si poteva estrarre tutti {} s ', rimuoverli, quindi operare sulla corda avanzi.
Vorrei sostituirli utilizzando preg_replace_callback . Con la richiamata è possibile tenere traccia dell'ordine e sostituirli con qualcosa come% var1%,% var2%, ecc.
Non credo che ci sia un modo per esplodere da spazi, ma non nelle parentesi graffe senza modificare la stringa in anticipo.
Ciò potrebbe essere fatto senza iterately regexp. Di eseguire iterazioni su l'intera stringa. Hai messo ogni personaggio in una variabile temporanea, a meno che non si trova uno spazio. Quando si trova uno spazio, si mette il contenuto della variabile temporanea nella matrice, svuotarlo, e poi continuare.
Se si trova una staffa, si imposta un valore booleano, e poi mettere tutto in temp var, fino a trovare una parentesi di chiusura. E così via.
<?php
$string = "write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly";
$bracket = false;
$words = array();
$temp = "";
for($i = 0; $i < strlen($string); $i++){
$char = $string[$i]
if($bracket){
$temp .= $char;
if($char == "}"){
$bracket = false;
$words[] = $temp;
}
}
else{
if($char == " "){
if($temp != ""){
$words[] = $temp;
$temp = "";
}
}
elseif($char == "{"}{
$temp .= $char;
$bracket = true;
}
else{
$temp .= $char;
}
}
}
?>
Codice è testato.
Si desidera dividere in tutti gli spazi che non sono contenuti all'interno di parentesi graffe.
Abbinare le espressioni ricci o una sequenza di caratteri che non sono spazi quindi ignorare queste partite con \K
quindi utilizzare il seguente spazio come delimitatore.
Codice: ( Demo )
$text = 'write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly';
var_export(preg_split('~({[^}]*}|\S+)\K ~', $text));
P.S. È possibile sostituire le parentesi graffe con forti tag come questo: https://3v4l.org/fXrgE
p.p.s. Si potrebbe costruire la vostra lista ordinata esatto con preg_replace_callback()
: ( Demo ) <- trasferimento in phptester.net per vederlo reso
$text = 'write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly';
echo "<ol>" , preg_replace_callback('~{([^}]*)}|(\S+)~', function($m) {
if (!isset($m[2])) {
return "<li><strong>{$m[1]}</strong></li>\n";
}
return "<li>{$m[2]}</li>\n";
},
$text) , "<ol>";