¿Cómo devolver la primera subcadena coincidente de una cadena usando Ruby regex? [duplicar]
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
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