Я на самом деле не знаю, что означает bla/bla/bla/Prefix@invoice.csv
;bla/bla/bla/bla
все каталоги и имя файла Prefix@invoice.csv
?
Исходя из предположения, что я правильно понял ваши имена файлов, я предлагаю использовать File.split()
:
irb> (path, name) = File.split("bla/bla/bla/Prefix@invoice.csv")
=> ["bla/bla/bla", "Prefix@invoice.csv"]
irb> (prefix, postfix) = name.split("@")
=> ["Prefix", "invoice.csv"]
Не толькоЯвляется ли он платформо-независимым, он более разборчивый.
Обновление
Вы пробудили мое любопытство:
>> wpath="blah\\blah\\blah\\Prefix@invoice.csv"
=> "blah\\blah\\blah\\Prefix@invoice.csv"
>> upath="bla/bla/bla/Prefix@invoice.csv"
=> "bla/bla/bla/Prefix@invoice.csv"
>> r=Regexp.new(".+[\\\\/]([^@]+)@(.+)")
=> /.+[\\\/]([^@]+)@(.+)/
>> wpath.match(r)
=> #<MatchData "blah\\blah\\blah\\Prefix@invoice.csv" 1:"Prefix" 2:"invoice.csv">
>> upath.match(r)
=> #<MatchData "bla/bla/bla/Prefix@invoice.csv" 1:"Prefix" 2:"invoice.csv">
Вы правы,\
должен быть дважды экранирован, чтобы он работал в регулярном выражении: один раз, чтобы пройти через интерпретатор, еще раз, чтобы пройти через механизм регулярных выражений.(Определенно чувствует себя неловко.) Регулярное выражение:
.+[\\/]([^@]+)@(.+)
Строка:
".+[\\\\/]([^@]+)@(.+)"
Регулярное выражение, которое может быть слишком хрупким для реального использования (как оно будет обрабатывать путьбез /
или \
разделителей пути или пути без @
или со слишком большим количеством @
?), ищет любое количество символов, один разделитель пути, любое количество не-, @, затемлюбое количество любых символов.Я предполагаю, что первый .+
будет жадно потреблять как можно больше символов, чтобы максимально приблизить совпадение к вправо :
>> evil_path="/foo/bar@baz/blorp/Prefix@invoice.csv"
=> "/foo/bar@baz/blorp/Prefix@invoice.csv"
>> evil_path.match(r)
=> #<MatchData "/foo/bar@baz/blorp/Prefix@invoice.csv" 1:"Prefix" 2:"invoice.csv">
Но в зависимости от искаженного вводаданные, это может сделать очень неправильно.