2011-10-03 10 views
6

Supongo que esto será un error tonto, pero para mí, lo siguiente devuelve una matriz que contiene solo "M". Ver esto:Ruby Regex, Only One Capture (¡Muy simple!)

/(.)+?/.match("Many many characters!").captures 
=> ["M"] 

¿Por qué no devuelve una matriz de cada carácter? Debo haberme olvidado algo descaradamente obvio porque no puedo ver lo que está mal con esto?

Editar: ¿Acabo de dar cuenta, no necesito el +? pero todavía no funciona sin eso.

Edit: Disculpas! Aclararé: mi objetivo es permitir que los usuarios ingresen una expresión y un estilo regulares y un archivo de texto de entrada, donde haya una coincidencia, el texto estará rodeado por un elemento html y se aplicará el estilo, no solo estoy dividiendo el en caracteres, solo usé la expresión regular dada porque era la más simple aunque eso era estúpido de mi parte. ¿Cómo obtengo grupos de captura de scan() o no es posible? Veo que $ 1 contiene "!" (último partido?) y no otros.

Edit: Dios mío, realmente no es mi día. Como injekt me ha informado, las capturas se almacenan en matrices separadas. ¿Cómo obtengo el desplazamiento de estas capturas desde la cadena original? Me gustaría poder obtener el desplazamiento de una captura y luego rodearlo con otra cuerda. ¿O es para lo que es el gsub? (Pensé que sólo reemplaza el partido, no un grupo de captura)

Esperemos edición final: derecho, permítanme empezar de nuevo: P

lo tanto, tengo una cadena. El usuario usará un archivo de configuración para ingresar una expresión regular, luego un estilo asociado con cada grupo de captura. Necesito poder escanear toda la cadena y obtener el inicio y el final o el desplazamiento y el tamaño de cada coincidencia de grupo.

lo tanto, si un usuario ha configurado ([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4}) (correo electrónico) entonces yo debería ser capaz de obtener:

[ ["elliotpotts", 0, 11], 
    ["sample.",  12, 7], 
    ["com",   19, 3] ] 

de la cadena: "[email protected]"

Si eso no es claro, simplemente hay algo mal conmigo: P. Muchas gracias, muchachos hasta ahora, ¡y gracias por ser tan pacientes!

+0

acabo de ver tu edición, grupos de captura de exploración se almacenan en matrices independientes, sólo tratar su expresión regular y una cadena de prueba en el IRB verá. Las respuestas siguen siendo las mismas con su edición incluida –

+0

Acabo de ver su próxima edición, deberá actualizar con más información. Estoy un poco confundido ahora: P Siéntase libre de arrojar un ejemplo más completo sin importar cuán artificial sea, para que sepamos exactamente lo que necesita extraer –

+0

Muy bien, actualicé mi respuesta con su última edición. Estoy un poco atada por el tiempo ahora, así que es solo la solución completa sin explicación, avíseme si no tiene sentido y la actualizaré –

Respuesta

9

Debido a que su captura sólo se está emparejando uno carácter individual.(.)+ no es lo mismo que (.+)

>> /(.)+?/.match("Many many characters!").captures 
=> ["M"] 
>> /(.+)?/.match("Many many characters!").captures 
=> ["Many many characters!"] 
>> /(.+?)/.match("Many many characters!").captures 
=> ["M"] 

Si desea hacer coincidir todos los personajes usan de forma recursiva String#scan o String#split si no se preocupan por los grupos de captura

Utilizando análisis:

"Many many characters!".scan(/./) 
#=> ["M", "a", "n", "y", " ", "m", "a", "n", "y", " ", "c", "h", "a", "r", "a", "c", "t", "e", "r", "s", "!"] 

Nota esa otra respuesta está usando (.), mientras que está bien si te importa el grupo de captura, es un poco inútil si no lo haces, de lo contrario, devolverá CADA CARÁCTER en su n matriz separada, así:

[["M"], ["a"], ["n"], ["y"], [" "], ["m"], ["a"], ["n"], ["y"], [" "], ["c"], ["h"], ["a"], ["r"], ["a"], ["c"], ["t"], ["e"], ["r"], ["s"], ["!"]] 

De lo contrario, sólo tiene que utilizar split: "Many many characters!".split(' ')"

EDITAR En respuesta a su edición:

reg = /([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/ 
str = "[email protected]" 
str.scan(reg).flatten.map { |capture| [capture, str.index(capture), capture.size] } 
#=> [["elliotpotts", 0, 11], ["sample.", 12, 7], ["com", 19, 3]]` 

Ah, y que no necesita de exploración , en realidad no está escaneando, por lo que no necesita desplazarse, al menos no con el ejemplo que proporcionó:

str.match(reg).captures.map { |capture| [capture, str.index(capture), capture.size] } 

también trabajar

+0

¡Gracias! También encontré una respuesta alternativa y la publicaré ahora. ¡Gracias! – Ell

+0

Los dos fragmentos de código proporcionados no funcionan correctamente para los desplazamientos en el caso general, solo funcionan si las subcadenas coincidentes son todas diferentes. Si, por ejemplo, hay 3 coincidencias para "h", el mismo índice (la primera instancia de "h") se devuelve las 3 veces. the str.index (capture) devuelve el índice de la PRIMERA instancia de la subcadena capturada. – jpwynn

0

Solo devuelve un personaje porque eso es todo lo que ha pedido que coincida. Es posible que desee utilizar en lugar scan:

str = "Many many characters!" 
matches = str.scan(/(.)/) 
1

Sí, algo importante se ha perdido ;-)

(...) sólo introduce UN grupo de captura: el número de veces que coincide con el grupo es irrelevante, ya que el índice se determina solamente por la regularidad expresión en sí misma y no la entrada.

La clave es una "expresión regular global", que aplicará la expresión regular varias veces en orden. En Rubí esto se hace con la inversión de Regex#match-String#scan (muchos otros idiomas tienen un "/ g" modificador de la expresión regular):

"Many many chara­cters!".sc­an(/(.)+?/­) 
# but more simply (or see answers using String#split) 
"Many many chara­cters!".sc­an(/(.)/­) 

feliz de codificación

0

El código siguiente es de Get index of string scan results in ruby y modificado para mi gusto .

[].tap {|results| 
    "abab".scan(/a/) {|capture| 
     results.push(([capture, Regexp::last_match.offset(0)]).flatten) 
    } 
} 

=> [["a", 0], ["a", 2]]