2

ColdFusion で拡張子のないファイル名を取得しようとしています。私は次の機能を使用しています: REMatchNoCase( "(.+?)(\.[^.]*$|$)" , "Doe, John 8.15.2012.docx" );

これで次のような配列を返したいのです["Doe, John 8.15.2012","docx"] が、代わりに、常に 1 つの要素 (ファイル名全体) を持つ配列を取得します。["Doe, John 8.15.2012.docx"]

上記の正規表現文字列を rexv.org で試したところ、期待どおりに動作しましたが、ColdFusion では動作しませんでした。この SO の質問から文字列を取得しました: Regex: Get Filename Without Extension in One Shot?

ColdFusion は別の構文を使用しますか? それとも私は何か間違ったことをしていますか?

ありがとう。

4

3 に答える 3

8

なぜ期待した結果が得られないのか...

ファイル名全体で 1 項目の配列を取得する理由は、パターンがファイル名全体に一致し、1 回一致するためです。

2 つのグループをキャプチャしてますが、 rematchはキャプチャされたグループの配列ではなく、一致の配列を返すため、それらのグループは表示されません。

問題を解決する方法...

.htaccess単純なファイル (つまり、noまたは類似)を扱っている場合、最も簡単な解決策は、単に使用することです...

ListLast( filename , '.' )

....ファイル拡張子のみを取得し、拡張子なしで名前を取得するには...

rematch( '.+(?=\.[^.]+$)' , filename )

これは、先読みを使用して、文字列の最後に.少なくとも 1 つの非 - が続くことを確認.しますが、(これは先読みであるため) 一致から除外されます (したがって、一致では拡張前の部分のみが取得されます)。 .

拡張子のないファイル (.htaccessや などREADME) を処理するには、上記の正規表現を変更し.+(?=(?:\.[^.]+)?$)て、拡張子をオプションにする以外は基本的に同じことを行います。ただし、これらの ListLast メソッドを更新する簡単な方法はありません (確認する必要があると思いますlen(extension) LT len(filename)-1)。

(オプション)キャプチャされたグループにアクセスしています...

実際にキャプチャされたグループを取得したい場合、CF でこれを行うための最も近いネイティブな方法は、4 番目の引数を true に設定してrefind関数を使用することですがこれは位置と長さのみを提供します。それらを自分で抽出します。

この理由から (他の多くの理由の中でも)、CF 用の改良された正規表現実装を作成しました。これは cfRegex と呼ばれ、グループ テキストを直接返すことができます (つまり、mid をいじることはありません)。

cfRegex を使用したい場合は、次のように元のパターンで行うことができます。

RegexMatch( '(.+?)(\.[^.]*$|$)' , filename , 1 , 0 , 'groups' )

または名前付き引数を使用:

RegexMatch( pattern='(.+?)(\.[^.]*$|$)' , text=filename , returntype='groups' )

そして、一致の配列が返されます。各要素は、その一致のキャプチャされたグループの配列です。

キャプチャされたグループを扱う多くの正規表現作業を行っている場合、CF の re メソッドで行うよりもcfRegexの方が確実に優れています。

拡張子および/または拡張子を除外したファイル名を取得することだけが重要な場合は、上記の前の例で十分です。

于 2012-07-02T23:56:48.137 に答える
1

@Peter の応答は素晴らしいですが、このアプローチはおそらく必要以上にやや長めです。reMatch()正規表現を微調整することでこれを行うことができます。

<cfscript>
    param name="URL.filename";

    sRegex = "^.+?(?=(?:\.[^.]+?)?$)";

    aMatch = reMatch(sRegex, URL.filename);

    writeDump(aMatch);
</cfscript>

これは、次のファイル名パターンで機能します。

  • foo.bar
  • ふー
  • .htaccess
  • ジョン 8.15.2012.docx

正規表現の説明:

^ 文字列の先頭から

.+? 1 つ以上の (+) 文字 (.) ですが、正規表現の残りの部分で機能する最小 (?) です。これはファイル名です。

(?=) 前を向いて。ここにあるものが文字列に表示されることを確認しますが、実際には一致しません。これは、存在する可能性のあるファイル拡張子を返さないための重要なビットです。

    (?: これらをグループ化しますが、後方参照用に覚えないでください。

        . 点。これは、ファイル名とファイル拡張子の間の区切りです。

        [^.]+? 1 つまたは複数の (+) 単一 ([]) ドット以外の文字 (^.)。ここでも、全体として正規表現を機能させることができる最小の (?) に一致します。

    ? (これは (?:) グループの後のものです)。これらのグループのゼロまたは 1 つ: つまり、ゼロまたは 1 つのファイル拡張子。

    $ 文字列の最後まで

これら 4 つのファイル名パターンでのみテストしましたが、問題なく動作するようです。他の人はそれを微調整できるかもしれません。

于 2012-07-03T07:56:39.810 に答える
1

同じ結果を達成するためのいくつかの方法。それらはすべてほぼ同じ時間で実行されます。

<cfscript>
str = 'Doe, John 8.15.2012.docx';

// sans regex
arr1 = [
    reverse( listRest( reverse( str ), '.' ) ),
    listLast( str, '.' )
];

// using Java String lastIndexOf()
arr2 = [
    str.substring( 0, str.lastIndexOf( '.' ) ),
    str.substring( str.lastIndexOf( '.' ) + 1 )
];

// using listToArray with non-filename safe character replace
arr3 = listToArray( str.replaceAll( '\.([^\.]+)$', '|$1' ), '|' );
</cfscript>
于 2012-07-19T02:48:05.740 に答える