Ruby 中字符串的一部分递增
我在 Ruby 脚本中有一个方法,它尝试在保存文件之前重命名文件。它看起来像这样:
def increment (path)
if path[-3,2] == "_#"
print " Incremented file with that name already exists, renaming\n"
count = path[-1].chr.to_i + 1
return path.chop! << count.to_s
else
print " A file with that name already exists, renaming\n"
return path << "_#1"
end
end
假设您有 3 个同名文件保存到一个目录中,我们会说该文件名为 example.mp3
。这个想法是,第一个将保存为 example.mp3
(因为它不会被 if File.exists?("#{file_path}.mp3")
捕获> 脚本中的其他位置),第二个将保存为 example_#1.mp3
(因为它被上述方法的 else
部分捕获),第三个将保存为example_#2.mp3
(因为它被上述方法的 if
部分捕获)。
我遇到的问题是双重的。
1) if path[-3,2] == "_#"
不适用于整数超过一位的文件 (example_#11.mp3
例如),因为字符位置将是错误的(您需要它是 path[-4,2]
但这样就不能处理 3 位数字等)。
2)我永远不会遇到问题1),因为该方法不能可靠地捕获文件名。目前,它将第一个重命名为 example_#1.mp3
,但第二个将重命名为相同的内容(导致它覆盖以前保存的文件)。
这对于 Stack Overflow 来说可能太模糊了,但我找不到任何可以解决递增字符串特定部分问题的内容。
提前致谢!
编辑/更新:
韦恩的下面的方法似乎可以单独工作,但当作为整个脚本的一部分包含时则不行 - 它可以将文件增加一次(从 example.mp3
到example_#1.mp3
),但无法处理获取 example_#1.mp3
并将其递增到 example_#2.mp3
。为了提供更多上下文 - 当前,当脚本找到要保存的文件时,会将名称传递给 Wayne 的方法,如下所示:
file_name = increment(image_name)
File.open("images/#{file_name}.jpeg", 'w') do |output|
open(image_url) do |input|
output << input.read
end
end
我对 Wayne 的脚本进行了一些编辑,所以现在看起来像这样:
def increment (name)
name = name.gsub(/\s{2,}|(http:\/\/)|(www.)/i, '')
if File.exists?("images/#{name}.jpeg")
_, filename, count, extension = *name.match(/(\A.*?)(?:_#(\d+))?(\.[^.]*)?\Z/)
count = (count || '0').to_i + 1
"#{name}_##{count}#{extension}"
else
return name
end
end
我哪里出错了?再次提前致谢。
I have a method in a Ruby script that is attempting to rename files before they are saved. It looks like this:
def increment (path)
if path[-3,2] == "_#"
print " Incremented file with that name already exists, renaming\n"
count = path[-1].chr.to_i + 1
return path.chop! << count.to_s
else
print " A file with that name already exists, renaming\n"
return path << "_#1"
end
end
Say you have 3 files with the same name being saved to a directory, we'll say the file is called example.mp3
. The idea is that the first will be saved as example.mp3
(since it won't be caught by if File.exists?("#{file_path}.mp3")
elsewhere in the script), the second will be saved as example_#1.mp3
(since it is caught by the else
part of the above method) and the third as example_#2.mp3
(since it is caught by the if
part of the above method).
The problem I have is twofold.
1) if path[-3,2] == "_#"
won't work for files with an integer of more than one digit (example_#11.mp3
for example) since the character placement will be wrong (you'd need it to be path[-4,2]
but then that doesn't cope with 3 digit numbers etc).
2) I'm never reaching problem 1) since the method doesn't reliably catch file names. At the moment it will rename the first to example_#1.mp3
but the second gets renamed to the same thing (causing it to overwrite the previously saved file).
This is possibly too vague for Stack Overflow but I can't find anything that addresses the issue of incrementing a certain part of a string.
Thanks in advance!
Edit/update:
Wayne's method below seems to work on it's own but not when included as part of the whole script - it can increment a file once (from example.mp3
to example_#1.mp3
) but doesn't cope with taking example_#1.mp3
and incrementing it to example_#2.mp3
. To provide a little more context - currently when the script finds a file to save it is passing the name to Wayne's method like this:
file_name = increment(image_name)
File.open("images/#{file_name}.jpeg", 'w') do |output|
open(image_url) do |input|
output << input.read
end
end
I've edited Wayne's script a little so now it looks like this:
def increment (name)
name = name.gsub(/\s{2,}|(http:\/\/)|(www.)/i, '')
if File.exists?("images/#{name}.jpeg")
_, filename, count, extension = *name.match(/(\A.*?)(?:_#(\d+))?(\.[^.]*)?\Z/)
count = (count || '0').to_i + 1
"#{name}_##{count}#{extension}"
else
return name
end
end
Where am I going wrong? Again, thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正则表达式将完成:
这对于您正在编写的代码来说可能并不重要,但是如果您可能有多个线程或进程在同一文件上使用此算法,则在检查之前是否存在时会出现竞争条件保存:两个写入者都可以找到未使用的相同文件名并写入它。如果这对您很重要,请以某种模式打开该文件(如果存在),该模式会失败,从而挽救异常。当异常发生时,选择不同的名称。大致:
A regular expression will git 'er done:
This probably doesn't matter for the code you're writing, but if you ever may have multiple threads or processes using this algorithm on the same files, there's a race condition when checking for existence before saving: Two writers can both find the same filename unused and write to it. If that matters to you, then open the file in a mode that fails if it exists, rescuing the exception. When the exception occurs, pick a different name. Roughly:
这是不接受具有现有计数的文件名的变体:
证明:
Here's a variation that doesn't accept a file name with an existing count:
Proof: