0

私の入力文字列は次のようになります。

1    warning: rg: W, MULT: file 'filename_a.h' was listed twice.
2    warning: rg: W, SCOP: scope redefined in '/proj/test/site_a/filename_b.c'.
3    warning: rg: W, ATTC: file /proj/test/site_b/filename_c.v is not resolved.
4    warning: rg: W, MULTH: property file filename_d.vu was listed outside.

上記のように、4つの異なるフレーバーがあります。これらをログファイルから1行ずつ読み取ります。

パスが指定されているもの(2、3行目)の場合、を使用してファイル名を抽出でき$file=~s#.*/##;、正常に機能しているようです。異なるタイプの条件ステートメントを使用せず、ファイル名を抽出する方法はありますか?クリーンな正規表現を1つだけ使用して、ファイル名を抽出したいと思います。File::basenameこの場合もPerlは動作しません。

私はPerlを使用しています。

4

3 に答える 3

2

問題にはさらに制約が必要です。たとえば、文字列を「パス」(または「ファイル名」)として特徴付けるための良い方法は何ですか?「ねえ、文字と数字(記号ではない)の直後に1つのドットが表示され、そのドットの前にもたくさんの文字がある場合は、パスまたはファイル名である可能性があります!」と言うかもしれません。

\s+([^\s]+\.\w+)

ただし、これはすべてのパスをキャッチするわけではなく、拡張子のないファイルもキャッチしません。したがって、「上記のいずれか、または少なくとも1つのスラッシュが含まれる文字列」と言い換えることができます。

\s+([^\s]+\.\w+|[^\s]*\/[^\s]*)

(上記の例では、#区切り文字として使用しているように見えるため、スラッシュをエスケープする必要がない場合があることに注意してください。)

いずれにせよ、私が得ているのは、問題をより厳密に指定する必要があるということです。これにより、満足のいく解決策が自動的に得られます。もちろん、正規表現だけを使用する真の「正しい」解決策はありません。それを行うには、ファイルテストを実行する必要があります。

この例をさらに進めるために、拡張機能のリストを定義したい場合があります。

\s+([^\s]+\.(?:c|h|cc|cpp)|[^\s]*\/[^\s]*)

または、もっと一般的なものにしたいが、最大4文字の拡張機能のみを許可する場合もあります。

\s+([^\s]+\.\w{1,4}|[^\s]*\/[^\s]*)

おそらく、スラッシュで始まる場合にのみパスを検討しますが、それでも少なくとも1つのスラッシュをどこかに入れたいと考えています。

\s+([^\s]+\.\w{1,4}|/[^\s]*\/[^\s]*)

幸運を。

于 2012-05-31T20:14:07.950 に答える
2

あなたは2つのステップでそれを行うことができます:

  • 各行からパスを抽出します
  • パスからベース名を取得する

#!/usr/bin/perl -n
use feature 'say';
use File::Basename;

#NOTE: assume that unquoted path has no spaces in it 
say basename($1.$2) if /(?:file|redefined in)\s+(?:'([^']+)'|(\S+))/;

出力

filename_a.h
filename_b.c
filename_c.v
filename_d.vu
于 2012-05-31T20:43:24.767 に答える
0

/\w*.\w*/これは、4つの異なる警告ログに示されているファイル名と一致します。\ wは任意の単語文字(文字、数字、アンダースコア)に一致するため、この正規表現は任意の数の単語文字、ドット、さらに多くの単語文字を検索します。これが機能するのは、ログ内の他のドットがログの最後にあるためです。

于 2012-05-31T20:29:53.307 に答える