¿Por qué algunos comandos regex tienen interpretaciones opuestas de '\' con varios caracteres?

10

Tome, por ejemplo, este comando:

find . -regex ".*\.\(cpp\|h\)"

Esto encontrará todos los archivos .h y .cpp en su directorio. El carácter de punto '.' en expresiones regulares generalmente significa "cualquier caracter". Para que coincida solo con un período real, debe escapar usando el carácter de barra diagonal inversa '\'.

En este caso, dado un personaje con un significado especial, debe escapar de él para obtener el personaje real que representa.

Ahora, tome el paréntesis y la barra "o", que son los caracteres '(', ')' y '|', respectivamente. Estos también tienen significados especiales, utilizados para agrupar expresiones regulares. Sin embargo, para obtener el significado especial, ¡los caracteres deben escapar usando la barra invertida! Sin la barra invertida, los caracteres tienen el significado del carácter real que representa.

Porque es el '.' tratado de forma diferente a '(', ')' y '|'?

Cory Klein
fuente

Respuestas:

12

La respuesta es realmente "solo porque". Hay un montón de sintaxis de expresiones regulares diferentes, y aunque comparten una apariencia similar y, por lo general, los conceptos básicos son los mismos, varían en los detalles.

Históricamente, cada herramienta tenía su propia implementación nueva, haciendo lo que el autor pensara mejor. Hay un equilibrio entre hacer que los personajes sean especiales con y sin escape: demasiados personajes que son "naturalmente especiales" y terminas teniendo que escapar de ellos todo el tiempo solo para que coincidan con ellos; o, al revés, terminas necesitando un montón de escapes para usar la sintaxis común de expresiones regulares como () agrupación. Y todos los que escribieron un programa decidieron cómo hacerlo en función de las necesidades de su programa, en lo que sentían que era el enfoque correcto y en la fase de la luna.

Hay un intento de estandarización desde POSIX, que define " expresiones regulares básicas " y " expresiones regulares extendidas ". Asombrosamente, estos funcionan uno al lado del otro en lo que respecta a \, a veces , pero no con una consistencia perfecta.

Las expresiones regulares de Perl se han convertido en otro estándar de facto, por dos razones: primero, son muy flexibles y poderosas, y segundo, en realidad son bastante sensatas , con convenciones como "\ siempre escapa a un carácter no alfanumérico".

GNU Find tiene una -regextypeopción, donde puede cambiar la sintaxis de expresión regular utilizada. Lamentablemente, "perl" no es una opción, al menos en la versión de find que tengo. (El valor predeterminado es, no sorprendentemente de GNU, "emacs", y esa sintaxis se documenta aquí ).

mattdm
fuente