4

ファイルの拡張子を切り替えたいのですが。例えば:

test_dir/test_file.jpg与える.txt必要がありますtest_dir/test_file.txt

また、ソリューションが2つの拡張子を持つファイルで機能することを望んでいます。

test_dir/test_file.ext1.jpg与える.txtべきであるtest_dir/test_file.ext1.txt

同様に、拡張子のないファイルでは、拡張子を追加するだけです。

test_dir/test_file.txttest_dir/test_file.txtを指定する必要があります

これは簡単なはずだと思いますが、簡単な解決策は見つかりませんでした。これが私が今持っているものです。本当に醜いと思いますが、うまくいくようです。

def switch_ext(f, new_ext)
  File.join(File.dirname(f), File.basename(f, File.extname(f))) + new_ext
end

これを行うためのよりエレガントな方法はありますか?私はインターネットを見てきましたが、明らかな何かが欠けていると思います。知っておくべき落とし穴はありますか?正規表現を使用しないソリューションが好きです。

4

8 に答える 8

3

あなたの例の方法はそれほど醜いものではありません。文字列正規表現ではなく、ファイル命名セマンティック対応メソッドを引き続き使用してください。Pathnameあなたはそれを少しきれいにするかもしれないstdlibを試すことができます:

require 'pathname'

def switch_ext(f, new_ext)
  p = Pathname.new f
  p.dirname + "#{ p.basename('.*') }#{ new_ext }"
end

>> puts %w{ test_dir/test_file.jpg test_dir/test_file.ext1.jpg testfile .vimrc }.
 | map{|f| switch_ext f, '.txt' }
test_dir/test_file.txt
test_dir/test_file.ext1.txt
testfile.txt
.vimrc.txt
于 2012-11-15T01:32:47.200 に答える
1
def switch_ext(filename, new_ext)
  filename.chomp( File.extname(filename)) + new_ext
end

この長い議論の最後に、私自身の質問に対するこの答えが見つかりました。 http://www.ruby-forum.com/topic/179524

個人的には今まで見た中で最高だと思います。正規表現は覚えにくいため、エラーが発生しやすいため、絶対に避けたいと思います。

ドットファイルの場合、この関数はファイルに拡張子を追加するだけです。この振る舞いは私には理にかなっているようです。

switch_ext('.vimrc', '.txt') # => ".vimrc.txt"

引き続きより良い回答があれば投稿し、コメントを投稿して、この回答に不備がある場合はお知らせください。とりあえず質問は開いたままにしておきます。

于 2012-11-15T09:11:48.100 に答える
1

この種のタスクのために正規表現が発明されました。

def switch_ext f, new_ext
  f.sub(/((?<!\A)\.[^.]+)?\Z/, new_ext)
end

puts switch_ext 'test_dir/test_file.jpg', '.txt'
puts switch_ext 'test_dir/test_file.ext1.jpg', '.txt'
puts switch_ext 'testfile', '.txt'
puts switch_ext '.vimrc', '.txt'

出力:

test_dir/test_file.txt
test_dir/test_file.ext1.txt
testfile.txt
.vimrc.txt
于 2012-11-15T00:32:03.607 に答える
1
def switch_ext(f, new_ext)
  (n = f.rindex('.')) == 0 ?  nil : (f[0..n] + new_ext)
end

'.'それが最初の文字でない場合、それは最も正しい出現を見つけます。

于 2012-11-15T01:42:06.350 に答える
0

正規表現を使用することも、組み込みのファイル名操作ツールなどを使用することもできますFile

%w[
  test_dir/test_file.jpg
  test_dir/test_file.ext1.jpg
  test_dir/test_file
].each do |fn|
  puts File.join(
    File.dirname(fn),
    File.basename(fn, File.extname(fn)) + '.txt'
  )
end

どの出力:

test_dir/test_file.txt
test_dir/test_file.ext1.txt
test_dir/test_file.txt

私は個人的にFileメソッドを使用します。彼らはファイル名区切り文字に対するさまざまなOSのニーズを認識しているため、別のOSに移植するのは簡単です。あなたのユースケースでは、それは大したことではありません。パス操作を混ぜると、それがより重要になります。

于 2012-11-15T00:34:41.740 に答える
0
def switch_ext(filename, ext)
    begin
        filename[/\.\w+$/] = ext
    rescue
        filename << ext
    end
    filename
end

使用法

>> switch_ext('test_dir/test_file.jpeg', '.txt')
=> "test_dir/test_file.txt"

>> switch_ext('test_dir/no_ext_file', '.txt')
=> "test_dir/no_ext_file.txt"

この助けを願っています。

于 2012-11-15T03:08:18.627 に答える
0
def switch_ext f, new_ext
  "#{f.sub(/\.[^.]+\z/, "")}.#{new_ext}"
end
于 2012-11-15T03:12:01.850 に答える
0

Ruby 1.9.1以降、最も簡単な答えはPathname :: sub_ext(replacement)です。これは、拡張子を取り除き、指定された置換(空の文字列にすることができます'')に置き換えます。

Pathname.new('test_dir/test_file.jpg').sub_ext('.txt')
=> #<Pathname:test_dir/test_file.txt>

Pathname.new('test_dir/test_file.ext1.jpg').sub_ext('.txt')
=> #<Pathname:test_dir/test_file.ext1.txt>

Pathname.new('test_dir/test_file').sub_ext('.txt')
=> #<Pathname:test_dir/test_file.txt>

Pathname.new('test_dir/test_file.txt').sub_ext('')
=> #<Pathname:test_dir/test_file>

.注意すべきことの1つは、交換で主導権を握る必要があるということです。

Pathname.new('test_dir/test_file.jpg').sub_ext('txt')
=> #<Pathname:test_dir/test_filetxt>
于 2020-06-17T10:58:13.287 に答える