Me gustaría sugerir una solución que se diferencia de la anterior. Tenga en cuenta que el anterior usa obsoletoreturning
. Por cierto, es de todos modos específico para Rails, y no mencionó explícitamente Rails en su pregunta (solo como una etiqueta). Además, la solución existente no codifica .doc.pdf
en _doc.pdf
, como solicitó. Y, por supuesto, no colapsa los guiones bajos en uno.
aquí está mi solución:
def sanitize_filename(filename)
# Split the name when finding a period which is preceded by some
# character, and is followed by some character other than a period,
# if there is no following period that is followed by something
# other than a period (yeah, confusing, I know)
fn = filename.split /(?<=.)\.(?=[^.])(?!.*\.[^.])/m
# We now have one or two parts (depending on whether we could find
# a suitable period). For each of these parts, replace any unwanted
# sequence of characters with an underscore
fn.map! { |s| s.gsub /[^a-z0-9\-]+/i, '_' }
# Finally, join the parts with a period and return the result
return fn.join '.'
end
No ha especificado todos los detalles acerca de la conversión. Por lo tanto, estoy haciendo los siguientes supuestos:
- No debe haber como máximo una extensión de archivo, lo que significa que debe haber como máximo un periodo en el nombre del archivo
- Arrastrando períodos no marque el inicio de una extensión
- períodos que anteceden no marcan el inicio de una extensión
- Cualquier secuencia de caracteres más allá
A
- Z
, a
- z
, 0
- 9
y -
debería colapsarse en un solo _
(es decir subrayada se considera en sí mismo un carácter no permitido, y la cadena '$%__°#'
se convertiría en '_'
- en lugar de '___'
de las partes '$%'
, '__'
y '°#'
)
Lo complicado de esto es cuando me separé el nombre del archivo en la parte principal y extensión Con la ayuda de una expresión regular, estoy buscando el último período, que es seguido por algo más que un punto, de modo que no haya períodos siguientes que coincidan con los mismos criterios en la cadena. Sin embargo, debe ir precedido de algún carácter para asegurarse de que no sea el primer personaje de la cadena.
Mis resultados de las pruebas de la función:
1.9.3p125 :006 > sanitize_filename 'my§document$is°° very&interesting___thisIs%nice445.doc.pdf'
=> "my_document_is_very_interesting_thisIs_nice445_doc.pdf"
que creo que es lo que ha solicitado. Espero que esto sea lo suficientemente lindo y elegante.
Es una buena pregunta. Desearía que tuviera una respuesta stdlib –