2010-11-13 60 views
12

Imagínese que tengo la siguiente cadena:Regex: ¿cómo encontrar el valor entero máximo de un patrón?

"I'll have some %1%, some %42% and maybe some %5% as well." 

Básicamente, estoy interesado en saber el valor máximo entero que sigue el patrón% (entero)%.

Ni siquiera estoy seguro de que sea posible con una expresión regular. ¿Qué expresiones regulares podría usar para que en el ejemplo anterior la respuesta sea 42?

P.S. Una solución sencilla es, evidentemente, simplemente buscar cualquier% (entero)% de patrones, y usar el script (código de C++) para recorrer todas las coincidencias y encontrar el valor más alto. Mi pregunta es: ¿es posible hacerlo directamente dentro de la expresión regular?

Antecedentes: comprender lo que sigue probablemente no sea necesario para responder la pregunta, pero pensé que algunos de ustedes querrían saberlo.

Básicamente estoy usando C++ y boost :: format. Los formatos se modelan con marcadores de posición como este:% 1%,% 2%, etc. El formato Boost :: arroja una excepción si el número de variables suministradas no corresponde al valor entero máximo en el formato mismo. Los formatos que voy a utilizar son proporcionados por usuarios (de confianza) (administradores de sitios web). Aún así, para hacer las cosas correctamente, necesito validar el patten. Por lo tanto, necesito encontrar el entero máximo en el patrón para asegurarme de que no se lanzará ninguna excepción en el tiempo de ejecución.

Si está utilizando el formato boost :: con formatos proporcionados por el usuario, ¿cómo resolvió este problema?

¡Por cierto, no hay etiqueta de formato boost! (aunque hay otras etiquetas boost-foo).

Solución

Billy ONeal proporcionan la respuesta correcta y Beh Tou Cheh (en los comentarios a la respuesta seleccionada) tuvo la amabilidad de paste el código real:

#include <iostream> 
#include <string> 
#include <deque> 
#include "strtk.hpp" 

int main() 
{ 
    std::string s = "I'll have some %1%, some %42% and maybe some %5% as well."; 
    std::deque<int> int_list; 
    strtk::split_regex("%([\\d]+)%", 
         s, 
         strtk::range_to_type_back_inserter(int_list), 
         strtk::match_mode::match_1); 

    if (!int_list.empty()) 
    { 
     std::cout << "max: " << strtk::max_of_cont(int_list) << std::endl; 
    } 

    return 0; 
} 
+0

No conozco la biblioteca boost :: regex lo suficiente como para responder (solo aprenderla), pero recomendaría algo diferente a la simple solución que sugiera. Aunque los piratas informáticos de Perl pueden decirte lo contrario, esto no es lo que pretenden hacer las expresiones regulares. Son agradables para hacer coincidir cadenas pero una mala elección para la aritmética. –

+2

Realmente, no compliques las cosas al intentar meter todo en la expresión regular. Solo itera. – Amber

+0

Simplemente intentaría pasar los parámetros a la cadena de formato y convertirla en una cadena, todo dentro de una declaración try-catch que detecta una excepción de formato incorrecto. En realidad, no hay una forma simple de validar la cadena de formato que no sea para probarla. Por ejemplo, la cadena de formato también permite la sintaxis de printf. De lo contrario, si realmente quieres hacerlo, simplemente itera con una expresión regular simple: "% \ d +%". –

Respuesta

10

Encuentra todos los valores como este : %([\d]+)%, analiza la referencia posterior como un entero (usando algo como lexical_cast) y elige el valor más alto. (Puede usar algo como std::max_element para esto)

+1

Es decir, no itere sobre las soluciones, pero deje que la biblioteca lo haga por usted :) –

+0

@Billy: tendría que recortar el "%" inicial y final como la expresión regular que ha proporcionado devolverá, y lexical_cast lo hará barf una excepción bad_lexical_cast si les parece. –

+0

@Beh Tou Cheh: ¿Notaste el paréntesis en la expresión regular? Esos son importantes. No use la coincidencia completa, use la referencia inversa. –

0

Incluso si alguien diseñó una expresión regular capaz de hacer eso, no funcionaría tan bien como simplemente repetir las coincidencias.

Cuestiones relacionadas