Contenidos de etiquetas recursivas

Estoy buscando mejorar la expresión regular a continuación, ya que ahora también me gustaría hacer coincidir las etiquetas anidadas:

'%{if:\s*"\'([^\']*)\' == \'([^\']*)\'"}((?:(?!{else}|{/endif}).)*){else}((?:(?!{/endif}).)*){/endif}%sei'

Que básicamente coincide con:

{if: "'x' == 'y'"}
    a
{else}
    b
{/endif}

or

{if: "'x' == 'y'"}
    c
{/endif}

Sin embargo, me gustaría que esto fuera recursivo de alguna manera, por lo que las declaraciones anidadas también podrían coincidir sin romper nada (en el momento en que se rompe si se agrega una declaración anidada).

También habría una expresión similar con !=.

He encontrado esto http://www.devnetwork.net/viewtopic.php?f=38&t=102670&sid=02b7c691a2be894336c694700f8f911a#p551340 que coincide <div> etiquetas, aunque no estoy seguro de cómo adaptarlo para que se ajuste a mi expresión regular...

preguntado el 22 de mayo de 12 a las 11:05

más contexto por favor. ¿Cuál es el propósito de esto? -

Lo siento, es por alguna lógica que estoy permitiendo que algunos usuarios finales creen una plantilla para que aparezca con un área que pueden personalizar. No quiero permitir PHP, de modo que todo se elimine por seguridad tal como está tags -

¿Por qué no usas un motor de plantillas fácilmente disponible entonces? Twig si quieres PHP. De lo contrario XSLT. -

Un poco demasiado grande para mis necesidades y no requiere toda esa funcionalidad - if y else es todo lo que se necesita -

2 Respuestas

El uso de expresiones regulares (PCRE) no es óptimo en casos en los que necesitaría volver a analizar el contenido interno para cada nivel anidado (una de las razones por las que sería mejor usar un analizador adecuado).

Dicho esto, se puede hacer con un patrón como:

~
{if:\s*+
    (?<condition>
        [^{}]++
    )
}

(?<then>
    (?:
        (?:(?!{if:[^{}]++}|{else}|{/endif}).)*+
        (?R)*+
    )*+
)

(?:
    {else}
    (?<else>
        (?:
            (?:(?!{if:[^{}]++}|{else}|{/endif}).)*+
            (?R)*+
        )*+
    )
)?+

{/endif}
~six

Ejemplo de Perl @ idea.

En este texto

if: "'x' == 'y'"}
    a
{else}
    b
{/endif}

{if: "'x' == 'y'"}
    c
{/endif}

{if:minimal}{else}{/endif}

{if: "'nested' == 'things'"}
    {if: "'x' == 'y'"}x{if:minimal}{else}{/endif}x{/endif}
{else}
    b{if: "'x' == 'y'"}c{/endif}{if: "'x' == 'y'"}c{/endif}
{/endif}

{if:foo} unbalanced {if:bar}ignores first if{/endif}

concuerda

*** matched if:
  * cond: "'x' == 'y'"
  * then:
    a

  * else:
    b

*** matched if:
  * cond: "'x' == 'y'"
  * then:
    c

*** matched if:
  * cond: minimal
  * then:
  * else:
*** matched if:
  * cond: "'nested' == 'things'"
  * then:
    {if: "'x' == 'y'"}x{if:minimal}{else}{/endif}x{/endif}

  * else:
    b{if: "'x' == 'y'"}c{/endif}{if: "'x' == 'y'"}c{/endif}

*** matched if:
  * cond: bar
  * then: ignores first if

contestado el 22 de mayo de 12 a las 13:05

Gracias. ¿Seguiría funcionando si pusiera {$tag_name} entre comillas simples? - SeñorJ

perdon por ejemplo {if: "'{$tag_name}' == '123'"}true{else}false{/endif} - SeñorJ

@MrJ, no como es ahora. Cambie la expresión de condición ([^{}]++) a lo que quieras que acepte. - Qimpuesto

@MrJ, ¿no he respondido la pregunta? ¿O hay algo mal con la respuesta? - Qimpuesto

Si limita el anidamiento a una profundidad predeterminada (lo que podría o no ser una mala idea), podría hacerlo coincidir con una expresión regular. De lo contrario, no puedes. El enlace que proporcionó coincide con HTML con expresiones regulares, que se usa a menudo, pero es conocido ser una mala idea en general. Si no desea utilizar otras formas de análisis, considere hacer coincidir los if más internos, reemplazarlos con algo y volver a hacer coincidir.

contestado el 23 de mayo de 17 a las 13:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.