QA@IT

パス末尾のデリミタの有無を吸収したい

2939 PV

ファイル操作等のちょっとしたスクリプトを書く際に、
パスやURLの、末尾の"/"の有無を吸収したい場合があるのですが、
Rubyで簡潔な書き方があれば教えてください。

例えばコマンドラインからパスの入力を受け付けるスクリプトの場合、
"/home/hoge"と"/home/hoge/"のどちらを入力されても、
"/home/hoge/"に内部的に整形したいです。

現状は、下記のように書いています。

ARGV[0] = ARGV[0]+"/" if ARGV[0][ARGV[0].length-1] != "/"

より簡潔な書き方等ありましたら教えてください。

回答

末尾になければ追加というのを正規表現でそのまま書くと

["/home/hoge", "/home/hoge/"].map{|s| s.sub(/(?<!\/)\z/, '/') }

となります。

削る方に統一するのなら chomp('/') と簡潔に書けるので、

["/home/hoge", "/home/hoge/"].map{|s| s.chomp('/') + '/' }

とするのもわかりやすくて良いと思います。

編集 履歴 (0)
  • なるほど!chomp('/')は簡潔で分り易いですね。ありがとうございます -

そもそも "/" の有無を統一する必要があるというのは確かでしょうか?
ディレクトリ名とファイル名から、フルパス名を作るときに単純に + してませんか?
File.join() を使うと、末尾の "/" の有無を気にせずにつなげることができます。

どうしても、"/" ありに統一したいなら、
ARGV[0] = File.join(ARGV[0],"")

編集 履歴 (0)
  • なるほど、そんな便利なものが…。ありがとうございます!! -

そもそも / の有無を統一する必要があるかどうかは確かでしょうか?
ディレクトリ名とファイル名から、フルパス名を作るときに単純に + してませんか?
File.join を使うと、ディレクトリ名の末尾の / の有無を気にする必要がありません。

もしどうしても統一して / をつけたいなら、
ARGV[0] = File.join(ARGV[0],"")
で。

編集 履歴 (0)

好みの問題かもしれませんが、私なら以下のように書くかも。

str = ARGV.shift
path = str + '/' unless str[-1] == '/'

少なくとも、

ARGV[0][ARGV[0].length-1]

は、

ARGV[0][-1]

と書いても同じことなので、

ARGV[0] = ARGV[0]+"/" if ARGV[0][ARGV[0].length-1] != "/"

というのは、

ARGV[0] = ARGV[0]+"/" if ARGV[0][-1] != "/"

と書けますね。

RubyのArrayやStringではマイナスのインデックスは以下のように後ろから何番目というのを直感的に示せるので便利です。

> [0,1,2,3,4,5][-1]
=> 5
> [0,1,2,3,4,5][-2]
=> 4
> [0,1,2,3,4,5][-3]
=> 3
> [0,1,2,3,4,5][-3..-1]
=> [3, 4, 5]
> "abcde"[-1]
=> "e"
> "abcde"[-2]
=> "d"
> "abcde"[-3]
=> "c"
> "abcde"[-3..-1]
=> "cde"
編集 履歴 (1)
  • たしかに、ARGV[0][-1]でよかったですね…。まだまだRuby初心者です。ありがとうございます。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。