2017-09-18 24 views
0

私は以下のPerl文字列を持っています。長さとパターンは異なります。ファイルは常に私がlog前に、単語を抽出する必要がPerlで文字列の特定の部分を抽出します。

my $file1 = '/user/mike/desktop/sys/syslog.1'; 
my $file2 = '/user/mike/desktop/movie/dnslog.2'; 
my $file3 = '/haselog.3'; 
my $file4 = '/user/mike/desktop/movie/dns-sys.log' 

*log.999という名前です。この場合、sys,dns,haseおよびdns-sysである。

正規表現を使ってそれらを抽出するにはどうすればよいですか?

+0

「_ **ファイル**はXXXXlog.num_という名前ですが、あなたの例は_directory_、 '.../syslog.1/''を表示します(後続のスラッシュに注意してください)。そして、これは常に_名前/パスの最後のものですか? – zdim

+0

@zdim混乱して申し訳ありません。私は、ファイルの名前(XXXXlog.num)が途中で最後のものであることを意味しました。 – Luke

答えて

1

表示されている文字列の主な特性は、最後のというフレーズが*log*であることです。

その後、パターンを固定、もしそうなら.N拡張子が

my ($name) = $string =~ /(\w+)log(?:\.[0-9]+)?$/; 

オプションでありながら、私たちはどこか途中

my ($name) = $string =~ /(\w+)log\.[0-9]+$/; 

logと一致しません上記\w+パターンを使用していますlogの前のテキストをキャプチャします。しかし、そのテキストには、単語以外の文字(-.など)が含まれていることもあります。その場合は、Abigail's answerで指摘されているように、最後の/の後ろのすべてをキャプチャするのに[^/]+を使用します。私はreadibilityを支援することができますどのようなスペースが内部に無視されたと}x修飾子を、追加されたコメント

my ($name) = $string =~ m{ ([^/]+) log (?: \.[0-9]+)? $}x; 

に質問につき、.Nオプション付き。

/以外の区切り文字を使用して、/をエスケープせずに使用できるようにしてから、mが必須です。 [^...]は、の無効化された文字クラスであり、任意の文字に一致します。が内部にリストされています。したがって、[^/]+logは、logの前に来る/ではないすべての連続する文字と一致します。

非キャプチャグループ内の(?: ...)グループパターンに、?は、グループ全体に適用されますが、不必要にそれらを捕捉しないように。

(?:\.[0-9]+)?パターンは、log.(ドットなし)とlog5のようなものを禁止するように具体的に書かれています。これらが許容されている場合でも、コードにタイプミスを修正単純\.?[0-9]*

更新  のように変更します。.Nオプションがない、*

+0

小さな質問です。 ** my $ name **を使用するのではなく、** my($ name)**にかっこを追加する必要があるのはなぜですか? @ zim – Luke

+0

@ルークマッチ演算子( 'm /.../')が返すのは_context_に依存します。 'if($ v =〜/.../)'や '$ ret = $ v =〜/.../'(etc)にあるスカラーコンテキストではtrue/falseを返します。リストコンテキストでは、マッチの実際のリストを返します。だから私たちはそれにリストコンテキストを課す必要があります。これは括弧が '$ match = $ v =〜/.../'をします。あるいは、私は '@matches = $ v =〜/.../'と言うことができます。 – zdim

+0

この場合、true/falseを返します。私は私の$ filepathがスカラーコンテキストだと思う。それでtrue/falseを変換するには、parens()を使う必要があるのだろうか?私はかなり理解していない。ありがとうございます@zdim – Luke

2
\w+(?=log\b) 

試合log(なくloggingなど)が続いされる1つ以上の英数字を

ファイル名の形式が固定されている場合は、

\w+(?=log\.\d+\/$) 
を使用して、正規表現の信頼性を高めることができます
+1

'(\ w +)log \ b'を実行することもできます。 – melpomene

2

+があるために私が書くでしょうとしてその:

m {[^/]+(?=log\.[0-9]+$)} 

最後のスラッシュの後、そしてlog.NNNの部分の前にすべてをキャプチャする必要があります。いくつかの回答は、sysdnsのような名前を取得する\w+を使用しますが、e-mailのようなものでは失敗します。

+0

うん。それは起こるかもしれない。私はこの事件を起こすかもしれないことに気づいていません。ですから、@Abigailに感謝します。 – Luke

+0

これは私のコードです。なぜ実際の値ではなく** 1 **を印刷できますか? 'my($ name)= $ str =〜m {[^ /](?:\ log)?(?:[0-9] *)?$};' '$ name ; ' – Luke

+0

結果をキャプチャする場合は、キャプチャしたいパーティの周りに括弧を入れなければなりません。 さらに、regexpを悪用すると、マッチした文字列の最初のスラッシュ以外の文字が取得されるようになります。 – Abigail

関連する問題