私は持っています
$w="/fold1/fold2/qwerty.h"
/qwerty.hをカットして/fold1/fold2を取得したい
私は試した
$w=~s/\/.+\.h\z//; and $w=~s/\/.+?\.h\z//;
しかし、それらは文字列全体を削除します。
$w=~s/\/\w+\.h\z//;
動作しますが、qwerty.hの代わりにqwe\rty.hがあるとします。それは二度と機能しません。
私は持っています
$w="/fold1/fold2/qwerty.h"
/qwerty.hをカットして/fold1/fold2を取得したい
私は試した
$w=~s/\/.+\.h\z//; and $w=~s/\/.+?\.h\z//;
しかし、それらは文字列全体を削除します。
$w=~s/\/\w+\.h\z//;
動作しますが、qwerty.hの代わりにqwe\rty.hがあるとします。それは二度と機能しません。
標準ライブラリのモジュールの1つであるFile::Basenameを使用します。
use File::Basename;
my $dir = dirname( $path );
一般に、データが特定のタイプであることがわかっている場合は、それらをそのタイプとして扱うようにしてください。この場合、それがファイルパスであることがわかっているので、一般的な文字列のように扱うのではなく、ファイルパスのように扱います。
あなたがしていることについて考えてください。最後の後に削除したいので、パターンは「任意の文字」()や「単語文字」()ではなく、/
に基づいている必要があります/
.
\w
$w =~ s/\/[^\/]+\.h\z//;
/
これは、正規表現区切り文字として回避することで、より明確に記述されます。
$w =~ s,/[^/]+\.h\z,,;
とは言うFile::Basename
ものの、よりクリーンでより一般的にポータブルなソリューションです。
File::Basename
うまくいかない場合は、次のようにすることができます。
substr( $w, 0, rindex( $w, '/' ))
私はこれを頻繁に使用するので、これについていくつかのイディオムがあります。
sub rpos_of {
return unless 1 + ( my $pos = rindex( $_[0], $_[1] ));
return $pos || '0E0';
}
sub before_last {
return $_[0] unless my $pos = &rpos_of;
return substr( $_[0], 0, $pos );
}
sub after_last {
return $_[0] unless my $pos = &rpos_of;
return substr( $_[0], $pos + length( $_[1] ));
}
sub break_at_last {
return $_[0] unless my $pos = &rpos_of;
return ( substr( $_[0], 0, $pos )
, substr( $_[0], $pos + length( $_[1] ))
);
}
$w=~s#(.*)/[^/]+#\1#
これも機能します。最後の/を見つけて、文字列全体を最後の/の前の部分文字列に置き換えます。