web-dev-qa-db-ja.com

ディレクトリとファイル名を解析するための正規表現

一致するグループを使用して完全修飾パスのディレクトリとファイル名を解析する正規表現を作成しようとしています。

そう...

/var/log/xyz/10032008.log

group 1 to be "/var/log/xyz"およびgroup 2 to be "10032008.log"

簡単に思えますが、私は一致するグループを私の人生のために働かせることはできません。

注:一部の回答者が指摘したように、これはおそらく正規表現の適切な使用ではありません。一般的に、使用している言語のファイルAPIを使用することを好みます。私が実際にやろうとしているのはこれよりも少し複雑ですが、説明するのははるかに困難だったので、根本的な問題を最も簡潔に記述するために誰もが精通しているドメインを選択しました。

25
Mike Deck

これを試して:

^(.+)/([^/]+)$
29
Jeremy Ruten

非キャプチャグループ の正規表現をサポートする言語では:

((?:[^/]*/)*)(.*)

危険な正規表現を爆発させて説明します...

(
  (?:
    [^/]*
    /
  )
  *
)
(.*)

各部の意味:

(  -- capture group 1 starts
  (?:  -- non-capturing group starts
    [^/]*  -- greedily match as many non-directory separators as possible
    /  -- match a single directory-separator character
  )  -- non-capturing group ends
  *  -- repeat the non-capturing group zero-or-more times
)  -- capture group 1 ends
(.*)  -- capture all remaining characters in group 2

正規表現をテストするために、次のPerlスクリプトを使用しました...

#!/usr/bin/Perl -w

use strict;
use warnings;

sub test {
  my $str = shift;
  my $testname = shift;

  $str =~ m#((?:[^/]*/)*)(.*)#;

  print "$str -- $testname\n";
  print "  1: $1\n";
  print "  2: $2\n\n";
}

test('/var/log/xyz/10032008.log', 'absolute path');
test('var/log/xyz/10032008.log', 'relative path');
test('10032008.log', 'filename-only');
test('/10032008.log', 'file directly under root');

スクリプトの出力...

/var/log/xyz/10032008.log -- absolute path
  1: /var/log/xyz/
  2: 10032008.log

var/log/xyz/10032008.log -- relative path
  1: var/log/xyz/
  2: 10032008.log

10032008.log -- filename-only
  1:
  2: 10032008.log

/10032008.log -- file directly under root
  1: /
  2: 10032008.log
19
Chad Nouis

ほとんどの言語には、これを既に提供するパス解析関数があります。能力がある場合は、すぐに使用できるものを無料で使用することをお勧めします。

/がパス区切り文字であると仮定...

^(.*/)([^/]*)$

最初のグループはディレクトリ/パス情報が何であれ、2番目はファイル名になります。例えば:

  • / foo/bar/baz.log:「/ foo/bar /」はパス、「baz.log」はファイル
  • foo/bar.log:「foo /」はパス、「bar.log」はファイル
  • / foo/bar:「/ foo /」はパス、「bar」はファイル
  • / foo/bar /: "/ foo/bar /"はパスであり、ファイルはありません。
8
Travis Illig

何語?そして、なぜこの単純なタスクに正規表現を使用しますか?

mustの場合:

^(.*)/([^/]*)$

必要な2つの部分を提供します。括弧を引用する必要がある場合があります。

^\(.*\)/\([^/]*\)$

好みの言語構文に応じて。

しかし、最後の「/」文字を見つける言語の文字列検索機能を使用し、そのインデックスで文字列を分割することをお勧めします。

4
tzot

これはどうですか?

[/]{0,1}([^/]+[/])*([^/]*)

確定的:

((/)|())([^/]+/)*([^/]*)

厳しい:

^[/]{0,1}([^/]+[/])*([^/]*)$
^((/)|())([^/]+/)*([^/]*)$
1
Aurélien Ooms

推論:

私は試行錯誤の方法で少し研究しました。キーボードで使用可能なすべての値は、* nuxマシンの「/」を除くファイルまたはディレクトリとして適格であることがわかりました。

Touchコマンドを使用して、次の文字のファイルを作成し、ファイルを作成しました。

(以下のコンマ区切り値)
'!'、 '@'、 '#'、 '$'、 "'"、'% '、' ^ '、' '、' * '、'( '、') '、' ' 、 '"'、 '\'、 '-'、 '、'、 '['、 ']'、 '{'、 '}'、 '`'、 '〜'、 '>'、 '<'、 ' = '、' + '、'; '、': '、' | '

「/」(ルートディレクトリであるため)とファイルコンテナ/を作成しようとしたときにのみ失敗しました。

そして、.を実行したときに、現在のディレクトリtouch .の変更時刻を変更しました。ただし、file.logは可能です。

そしてもちろん、a-zA-Z0-9-(ハイペン)、_(アンダースコア)は機能するはずです。

結果

そのため、上記の理由から、ファイル名またはディレクトリ名には/スラッシュ以外のものを含めることができます。したがって、正規表現は、ファイル名/ディレクトリ名に存在しないものから派生します。

/(?:(?P<dir>(?:[/]?)(?:[^\/]+/)+)(?P<filename>[^/]+))/

ステップバイステップの正規表現作成プロセス

パターン説明

ステップ-1:一致するrootディレクトリから開始する

ディレクトリは、絶対パスの場合は/で始まり、相対パスの場合はディレクトリ名で始まります。したがって、0回または1回発生する/を探してください。

/(?P<filepath>(?P<root>[/]?)(?P<rest_of_the_path>.+))/

enter image description here

ステップ-2:最初のディレクトリを見つけてください。

次に、ディレクトリとその子は常に/で区切られます。また、ディレクトリ名には、/以外の任意の名前を使用できます。最初に/ var /を照合しましょう。

/(?P<filepath>(?P<first_directory>(?P<root>[/]?)[^\/]+/)(?P<rest_of_the_path>.+))/

enter image description here

ステップ-3:ファイルの完全なディレクトリパスを取得する

次に、すべてのディレクトリを一致させましょう

/(?P<filepath>(?P<dir>(?P<root>[/]?)(?P<single_dir>[^\/]+/)+)(?P<rest_of_the_path>.+))/

enter image description here

ここで、single_dirはyz/です。最初にvar/に一致し、次に同じパターンの次の出現、つまりlog/を見つけ、次に同じパターンの次の出現yz/を見つけたからです。したがって、最後に出現したパターンを示しました。

ステップ-4:ファイル名を一致させてクリーンアップする

これで、single_dir、filepath、rootなどのグループを決して使用しないことがわかります。したがって、それをクリーンアップしましょう。

それらをグループとして保持しますが、それらのグループをキャプチャしません。

そして、rest_of_the_pathは単なるファイル名です!そのため、名前を変更します。また、ファイルの名前には/が含まれないため、[^/]を保持することをお勧めします

/(?:(?P<dir>(?:[/]?)(?:[^\/]+/)+)(?P<filename>[^/]+))/

これにより、最終結果が得られます。もちろん、他にもいくつかの方法があります。私はここで方法の1つに言及しています。

enter image description here

上記で使用される正規表現ルールはここにリストされています

^は、文字列が次で始まることを意味します
(?P<dir>pattern)は、グループ名でグループをキャプチャすることを意味します。グループ名がdirfileの2つのグループがあります
(?:pattern)は、このグループまたは非キャプチャグループを考慮しないことを意味します。
?は、0または1に一致することを意味します。 +は1つ以上の[^\/]と一致することを意味し、スラッシュ(/)以外の任意の文字と一致することを意味します

[/]?は、絶対パスの場合は/で開始できることを意味し、そうでない場合は開始しません。したがって、/のゼロまたは1回の出現に一致します。

[^\/]+/は、スラッシュではない1つ以上の文字(/)の後にスラッシュ(/)が続くことを意味します。これは、var/またはxyz/と一致します。一度に1つのディレクトリ。

0
theBuzzyCoder

これを試して:

/^(\/([^/]+\/)*)(.*)$/

ただし、パスには末尾のスラッシュが残ります。

0
Lucas Oman

非常に遅い答えですが、これが役立つことを願っています

^(.+?)/([\w]+\.log)$

これは/の遅延チェックを使用し、受け入れられた答えを修正しました

http://regex101.com/r/gV2xB7/1