¿Cómo devolver la primera subcadena coincidente de una cadena usando Ruby regex? [duplicar]

Sep 17 2020

Estoy buscando una manera de realizar una coincidencia de expresiones regulares en una cadena en Ruby y obtener la primera subcadena coincidente y asignar una variable. He comprobado diferentes soluciones aquí en el desbordamiento de pila, pero hasta ahora no pude encontrar una solución adecuada.

Esta es mi cuerda

/usr/share/filebeat/reports/ui/local/20200904_151507/API/API_Test_suite/20200904_151508/20200904_151508.csv

Necesito obtener la primera subcadena de 20200904_151507. bueno, esta ruta de archivo puede cambiar de vez en cuando. Y también la subcadena. Pero el patrón es date_time. En la expresión regular a continuación, intenté obtener los primeros ocho (8) números, _ y los últimos seis (6) números. aquí están las soluciones que probé,

report_path[/^[0-9]{8}[_][0-9]{6}$/,1]
report_path.scan(/^[0-9]{8}[_][0-9]{6}$/).first

el report_pathvaribale anterior tiene la ruta completa del archivo que mencioné anteriormente. ¿Qué hice mal aquí?

Respuestas

Sumak Sep 17 2020 at 18:08

scandevolverá todas las subcadenas que coincidan con el patrón. Puede usar match, scano []para lograr su objetivo:

report_path = '/usr/share/filebeat/reports/ui/local/20200904_151507/API/API_Test_suite/20200904_151508/20200904_151508.csv'

report_path.match(/\d{8}_\d{6}/)[0]
# => "20200904_151507"

report_path.scan(/\d{8}_\d{6}/)[0]
# => "20200904_151507"

# String#[] supports regex
report_path[/\d{8}_\d{6}/]
# => "20200904_151507"

Tenga en cuenta que matchdevuelve un MatchDataobjeto, que puede contener múltiples coincidencias (si usamos grupos de captura). scandevolverá un que Arraycontiene todas las coincidencias.

Aquí estamos llamando [0]al MatchDatallegar el primer partido


Grupos de captura:

Regex nos permite capturar múltiples subcadenas usando un patrón. Podemos utilizar ()para crear grupos de captura. (?'some_name'<pattern>)nos permite crear grupos de captura con nombre.

report_path = '/usr/share/filebeat/reports/ui/local/20200904_151507/API/API_Test_suite/20200904_151508/20200904_151508.csv'

matches = report_path.match(/(\d{8})_(\d{6})/)
matches[0]       #=> "20200904_151507"
matches[1]       #=> "20200904"
matches[2]       #=> "151507"


matches = report_path.match(/(?'date'\d{8})_(?'id'\d{6})/)
matches[0]       #=> "20200904_151507"
matches["date"]  #=> "20200904"
matches["id"]    #=> "151507"

Incluso podemos usar grupos de captura (con nombre) con []

De la String#[]documentación:

Si se proporciona un Regexp, se devuelve la parte correspondiente de la cadena. Si una captura sigue la expresión regular, que puede ser el índice o el nombre de un grupo de captura, sigue la expresión regular, ese componente de MatchData se devuelve en su lugar.

report_path = '/usr/share/filebeat/reports/ui/local/20200904_151507/API/API_Test_suite/20200904_151508/20200904_151508.csv'

# returns the full match if no second parameter is passed
report_path[/(\d{8})_(\d{6})/]
# => 20200904_151507

# returns the capture group n°2
report_path[/(\d{8})_(\d{6})/, 2]
# => 151507

# returns the capture group called "date"
report_path[/(?'date'\d{8})_(?'id'\d{6})/, 'date']
# => 20200904