Quiero dividir una cadena según los parámetros establecidos en el título. Probé algunas cosas diferentes, incluido el uso de preg_match sin mucho éxito hasta ahora y siento que puede haber una solución más simple que no he encontrado.
Tengo una expresión regular que coincide con el "precio" mencionado en el título (ver más abajo).
/(?=.)\£(([1-9][0-9]{0,2}(,[0-9]{3})*)|[0-9]+)?(\.[0-9]{1,2})?/
Y aquí hay algunos escenarios de ejemplo y cuál sería mi resultado deseado:
Ejemplo 1:
input: "This string should not split as the only periods that appear are here £19.99 and also at the end." output: n/aEjemplo 2:
input: "This string should split right here. As the period is not part of a price or at the end of the string." output: "This string should split right here"Ejemplo 3:
input: "There is a price in this string £19.99, but it should only split at this point. As I want it to ignore periods in a price" output: "There is a price in this string £19.99, but it should only split at this point"sugiero usar
preg_split('~\£(?:[1-9]\d{0,2}(?:,\d{3})*|[0-9]+)?(?:\.\d{1,2})?(*SKIP)(*F)|\.(?!\s*$)~u', $string)Vea la demostración de expresiones regulares .
El patrón coincide con su patrón, \£(?:[1-9]\d{0,2}(?:,\d{3})*|[0-9]+)?(?:\.\d{1,2})? y lo omite con (*SKIP)(*F) , de lo contrario, coincide con un no final . con \.(?!\s*$) (incluso si hay caracteres de espacio en blanco al final).
Si realmente solo necesita dividir en la primera aparición del punto de calificación, puede usar un enfoque de coincidencia:
preg_match('~^((?:\£(?:[1-9]\d{0,2}(?:,\d{3})*|[0-9]+)?(?:\.\d{1,2})?|[^.])+)\.(.*)~su', $string, $match)Vea la demostración de expresiones regulares . Aquí,
^ - coincide con una posición de inicio de cadena((?:\£(?:[1-9]\d{0,2}(?:,\d{3})*|[0-9]+)?(?:\.\d{1,2})?|[^.])+) - una o más apariciones de su patrón de moneda o cualquier otro carácter que no sea un . carbonizarse\. - un . carbonizarse(.*) - Grupo 2: el resto de la cadena.Para dividir un texto en oraciones evitando las diferentes trampas como puntos o separadores de miles en números y algunas abreviaturas (como etc. ), la mejor herramienta esintlBreakIterator diseñada para tratar con lenguaje natural:
$str = 'There is a price in this string £19.99, but it should only split at this point. As I want it to ignore periods in a price'; $si = IntlBreakIterator::createSentenceInstance('en-US'); $si->setText($str); $si->next(); echo substr($str, 0, $si->current()); IntlBreakIterator::createSentenceInstance devuelve un iterador que da los índices de las diferentes oraciones en la cadena.
Se toma en cuenta ? , ! y ... también. Además de las trampas de los números o los precios, también funciona bien con este tipo de cadena:
$str = 'John Smith, Jr. was running naked through the garden crying "catch me! catch me!", but no one was chasing him. His psychatre looked at him from the window with a circumspect eye.'; Más sobre las reglas utilizadas por IntlBreakIterator aquí .
Simplemente podría usar esta expresión regular:
\. Dado que solo tiene un espacio después de la primera oración (y no un precio), esto debería funcionar igual de bien, ¿verdad?