在Ruby中增加字符串的一部分

Rik*_*Rik 1 ruby string increment

我在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
Run Code Online (Sandbox Code Playgroud)

假设您将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来说太模糊了,但我找不到任何能解决增量字符串某个部分的问题.

提前致谢!

编辑/更新:

Wayne的方法似乎在它自己的方法上工作,但是当它作为整个脚本的一部分被包含时 - 它可以递增一个文件一次(从example.mp3example_#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    
Run Code Online (Sandbox Code Playgroud)

我已经编辑了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
Run Code Online (Sandbox Code Playgroud)

我哪里错了?再次,在此先感谢.

Way*_*rad 7

正则表达式将完成:

#!/usr/bin/ruby1.8

def increment(path)
  _, filename, count, extension = *path.match(/(\A.*?)(?:_#(\d+))?(\.[^.]*)?\Z/)
  count = (count || '0').to_i + 1
  "#{filename}_##{count}#{extension}"
end

p increment('example')        # => "example_#1"
p increment('example.')       # => "example_#1."
p increment('example.mp3')    # => "example_#1.mp3"
p increment('example_#1.mp3') # => "example_#2.mp3"
p increment('example_#2.mp3') # => "example_#3.mp3"
Run Code Online (Sandbox Code Playgroud)

这可能与您正在编写的代码无关,但如果您在同一文件中使用此算法可能有多个线程或进程,则在保存之前检查存在时存在竞争条件:两个编写者都可以找到相同的filename未使用并写入.如果这对您很重要,那么以一种失败的模式打开文件(如果它存在),挽救异常.发生异常时,请选择其他名称.大致:

loop do
  begin
    File.open(filename, File::CREAT | File::EXCL | File::WRONLY) do |file|
      file.puts "Your content goes here"
    end
    break
  rescue Errno::EEXIST
    filename = increment(filename)
    redo
  end
end
Run Code Online (Sandbox Code Playgroud)