2008-11-24 13 views

Respuesta

11

Algunas bibliotecas regex a llow búsqueda hacia delante:

somefile(?!16\.txt$).*?\.txt 

De lo contrario, todavía se puede utilizar varias clases de personajes:

somefile([^1].|1[^6]|.|.{3,})\.txt 

o, para lograr la máxima portabilidad:

somefile([^1].|1[^6]|.|....*)\.txt 

[^(16)] significa: cualquier carácter, pero los apoyos, 1 y 6.

+0

¿Probablemente quiera un? allí de la siguiente manera: somefile (?! 16). *? \. txt –

+0

@Martin Brown: ¿Por qué? . *? es afaik inválido en la mayoría de los dialectos. . significa cualquier carácter, * cero o más ocurrencias. ¿Qué debería hacer el signo de interrogación? – phihag

+0

@phihag:. *? significa hacer el. * no codicioso. Es un uso especial del signo de interrogación. –

3
somefile_(?!16).*\.txt 

(?! 16) significa: afirme que es imposible hacer coincidir la expresión regular "16" comenzando en esa posición.

+0

Esto se romperá si {anything} incluye un punto: somefile_19700101.archive.txt no coincidirá. – phihag

5

La mejor solución ya se ha mencionado:

somefile_(?!16\.txt$).*\.txt 

esto funciona, y es lo suficientemente codicioso para tomar todo lo que venga de ella en la misma línea. Si usted sabe, sin embargo, que desea un nombre de archivo válido, me gustaría sugerir también la limitación de caracteres no válidos:

somefile_(?!16)[^?%*:|"<>]*\.txt 

Si está trabajando con un motor de expresiones regulares que no admite la búsqueda hacia delante, tendrá que ¡Considera cómo compensar eso! 16. Puede dividir los archivos en dos grupos, aquellas que comienzan con 1, y no son seguidos por 6, y los que comienzan con cualquier otra cosa:

somefile_(1[^6]|[^1]).*\.txt 

Si desea permitir somefile_16_stuff.txt pero NO somefile_16.txt , estas expresiones rectas anteriores no son suficientes. Tendrá que establecer su límite diferente:

somefile_(16.|1[^6]|[^1]).*\.txt 

Combine todo esto, y se termina con dos posibilidades, una que bloquea la instancia única (somefile_16.txt), y uno que bloquea todas las familias (somefile_16 * .txt). Yo personalmente creo que se prefiere la primera de ellas:

somefile_((16[^?%*:|"<>]|1[^6?%*:|"<>]|[^1?%*:|"<>])[^?%*:|"<>]*|1)\.txt 
somefile_((1[^6?%*:|"<>]|[^1?%*:|"<>])[^?%*:|"<>]*|1)\.txt 

En la versión sin quitar caracteres especiales por lo que es más fácil de leer:

somefile_((16.|1[^6]|[^1).*|1)\.txt 
somefile_((1[^6]|[^1]).*|1)\.txt 
4

Para obedecer estrictamente a su especificación y ser exigente, se debe utilizar en lugar :

^somefile_(?!16\.txt$).*\.txt$ 

para que somefile_1666.txt que es {nada} puede ser igualada;)

pero a veces es más legible de usar ...:

ls | grep -e 'somefile_.*\.txt' | grep -v -e 'somefile_16\.txt' 
2

A veces es simplemente más fácil usar dos expresiones regulares. Primero busca todo lo que quieras, luego ignora todo lo que no quieres. Hago esto todo el tiempo en la línea de comandos donde canalizo una expresión regular que obtiene un superconjunto en otra expresión regular que ignora cosas que no quiero.

Si el objetivo es hacer el trabajo en vez de encontrar la expresión regular perfecta, tenga en cuenta ese enfoque. A menudo es mucho más fácil escribir y comprender que una expresión regular que hace uso de características exóticas.

1

Sin utilizar lookahead

somefile_(|.|[^1].+|10|11|12|13|14|15|17|18|19|.{3,}).txt 

leerlo como: somefile_ indicándose a continuación:

  1. nada.
  2. un personaje.
  3. cualquier carácter excepto 1 y seguido de cualquier otro carácter.
  4. tres o más caracteres.
  5. cualquiera 10 .. 19 tenga en cuenta que 16 se ha quedado afuera.

y finalmente seguido de .txt.

Cuestiones relacionadas