2012-05-14 16 views
6

Tengo problemas para capturar los dígitos en una cadena de este formato (t|b|bug_|task_|)1234 usando bash regex. El siguiente no funciona:¿Cómo hacer coincidir un "algo o nada" en un bash regex?

[[ $current_branch =~ ^(t|b|bug_|task_|)([0-9]+) ]] 

Pero una vez que lo cambio a algo como esto:

[[ $current_branch =~ ^(t|b|bug_|task_)([0-9]+) ]] 

funciona, pero por supuesto que su mal, ya que no cubre el caso donde hay sin prefijos Soy consciente de que en este caso lo que podía hacer

[[ $current_branch =~ ^(t|b|bug_|task_)?([0-9]+) ]] 

y lograr el mismo resultado, pero me gustaría saber por qué el segundo ejemplo no funciona. Esa expresión regular parece funcionar bien en Ruby, por ejemplo.

(Este es el GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11), OS X Lion)

+0

¿Intentó '(^ t |^b |^bug_ |^task_ |^$) ...' (o similar)?¿Y no es el carácter comodín '*' char = 'el algo o nada'? Buena suerte. – shellter

+1

'[[23 = ~ = ~^(t | b | bug_ | task_ |) ([0-9] +)]]' funciona para mí. ¿Qué es un ejemplo de un '$ current_branch' no funcional? ¿Qué constituye "no funciona"? ¿Qué versión de Bash? –

+0

Entonces, la pregunta es por qué '' [[$ current_branch = ~^(t | b | bug_ | task_ |) ([0-9] +)]] 'coincide, digamos,' 123'? – RichardTowers

Respuesta

2

Estoy seguro de que la diferencia entre las versiones de trabajo y no de trabajo de la expresión regular se basa en las diferentes formas de leer regex (7). Voy a citar toda la parte pertinente, porque creo que va al corazón de su problema:


Las expresiones regulares ("re" s), según se define en POSIX.2, entra dos formas: modernos REs (aproximadamente los de egrep; POSIX.2 llama a estos RE "extendidos") y obsoletos RE (aproximadamente los de ED (1); POSIX.2 "básicos" RE). Los RE obsoletos existen principalmente por compatibilidad con versiones anteriores en algunos programas antiguos; se discutirán en el extremo . POSIX.2 deja algunos aspectos de la sintaxis y la semántica de RE abiertas; "(!)" marca decisiones sobre estos aspectos que pueden no ser totalmente portátiles para otras implementaciones POSIX.2 .

A (moderno) RE es uno (!) O más no vacíos (!) branches, separados por '|'. Es coincide con cualquier cosa que coincida con una de las ramas.

Una rama es uno (!) O más piezas, concatenados. Se ajusta a la altura de la primero, seguido de un partido para el segundo, etc.

Una pieza es un átomo de posiblemente seguido por un solo (!) '*', '+', '?', o obligado. Un átomo seguido de '*' coincide con una secuencia de 0 o más coincidencias del átomo. Un átomo seguido de '+' coincide con una secuencia de 1 o más coincidencias del átomo. Un átomo seguido de '?' coincide con una secuencia de 0 o 1 coincidencias del átomo.

Un límite es '{' seguido de un entero decimal sin signo, posiblemente seguido de ',' posiblemente seguido de otro entero decimal sin signo, siempre seguido por '}'. Los enteros deben estar entre 0 y RE_DUP_MAX (255 (!)) Inclusive, y si hay dos de ellos, el primero no puede exceder el segundo.Un átomo seguido de un límite que contiene un número entero iy ninguna coma coincide con una secuencia de exactamente i coincidencias del átomo. Un átomo seguido de un límite que contiene un entero entero iy una coma coincide con una secuencia de i o más coincidencias del átomo. Un átomo seguido de un límite que contiene dos enteros i y j coincide con una secuencia de i a j (inclusive) coincidencias del átomo.

Un átomo es una expresión regular dentro "()" (ajustándose con una aparición del expresión regular), un conjunto vacío de "()" (coincidente con la cadena nula) (!), Una expresión soporte (vea abajo), '.' (coincidiendo con cualquier carácter), '^' (que coincide con la cadena nula al comienzo de una línea), '$' (que coincide con la cadena nula al final de una línea), un '\' seguido de uno de los caracteres "^. [$() | * +? {\" (que coincide con ese carácter tomado como un carácter ordinario), un '\' seguido de cualquier otro carácter (!) (que coincide con ese carácter tomado como un carácter ordinario , como si el '\' no hubiera estado presente (!)), o un solo carácter sin otro significado (que coincida con ese carácter). A '{' seguido de un carácter que no sea un dígito es un carácter ordinario, no el principio de un límite (!). Es ilegal finalizar un RE con '\'.


bien, hay mucho aquí para desempacar. En primer lugar, tenga en cuenta que el símbolo "(!)" Significa que hay un problema abierto o no portátil.

La cuestión esencial es en el siguiente párrafo:

A (moderna) es una o más ramas no vacío , separadas por '|' (!) (!).

Su caso es que usted tiene una sucursal vacía. Como puede ver en el "(!)", La rama vacía es un problema abierto o no portátil. Creo que es por eso que funciona en algunos sistemas, pero no en otros. (Lo probé en la versión de Cygwin 4.1.10 (4), y no funcionó, luego en la versión de Linux 3.2.25 (1), y lo hizo. Los dos sistemas tienen páginas de manual equivalentes, pero no idénticas, para regex7.)

Suponiendo que las ramas deben ser no vacías, una rama puede ser una pieza, que puede ser un átomo.

Un átomo puede ser "un conjunto vacío de"() "(que coincide con la cadena nula) (!)". <sarcasm> Bueno, eso es realmente útil. </sarcasm> Por lo tanto, POSIX especifica una expresión regular para la cadena vacía, es decir, (), pero también agrega un "(!)", Para decir que este es un problema abierto o no portátil.

Desde lo que estás buscando es una rama que coincida con la cadena vacía, tratar

[[ $current_branch =~ ^(t|b|bug_|task_|())([0-9]+) ]] 

que utiliza la expresión regular () para que coincida con la cadena vacía. (Esto funcionó para mí en mi shell Cygwin 4.1.10 (4), donde su expresión regular original no).

Sin embargo, aunque (afortunadamente) esta sugerencia funcionará para usted en su configuración actual, no hay garantizar que será portátil. Lamento decepcionar.

+0

¡Guau, una respuesta realmente magnífica! ¡Gracias por su arduo trabajo! – Suan

+0

Desafortunadamente, esto ahora parece coincidir con todo, algo tan simple como '[[" $ foo "= ~^(bar |())]]' coincidirá si 'foo = baz' etc., incluidas todas las variables que están vacías. Terminé yendo con '^ $' en su lugar, lo que de hecho funciona. GNU bash, versión 4.4.12 (1) - liberación (x86_64-redhat-linux-gnu) – xenithorb

0

[[ $current_branch =~ ^(t|b|bug_|task_|)([0-9]+) ]] funciona para mí en bash 4.1.2, pero falla en bash 3.2.48. Podría ser un error que se solucionó entre las dos versiones.

+0

No está directamente relacionada con la versión de bash - ver mi respuesta. – JXG

Cuestiones relacionadas