3

私はいくつかのperl正規表現をやろうとしてきましたが、壁にぶつかりました。ログ ファイルのデータ分析を実行しようとしていますが、次の問題が発生しています。

次のレイアウト形式を生成する別のプログラムからの複数の単一行エントリで構成されるファイル test.csv があります。

  • d:\snow\dir.txt
  • d:\snow\history\dir.tff
  • d:\snow\history\help.jar
  • d:\冬\show\help.txt
  • d:\summer\beach\ocean\swimming.txt

私がやりたいのは、パスリストからファイル名を削除することです。結果のファイルには次のものが含まれます。

  • d:\雪\
  • d:\雪\歴史\
  • d:\雪\歴史\
  • d:\冬\ショー\
  • d:\夏\ビーチ\海\

私はこれで壁に頭をぶつけて、ファイル名を削除しようとしてさまざまな perl regex を試しましたが、あまり運がありませんでした。ディレクトリへのパスの長さはさまざまであるため、壁にぶつかっています。これが perl または python 内で実行できるかどうかわかりません。

4

4 に答える 4

4

これは、Perl では 1 行で実行できます。

perl -pe 's/[^\\]+$/\n/' <infile.txt >outfile.txt

これをバラバラにすると:

-pPerl はステートメント ( で提供-e) をwhileループでラップし、そのステートメントを入力ファイルの各行に適用し、結果を出力します。

-eすべての行に対して実行するステートメントを Perl に与えます。

s/[^\\]+$/\n/正規表現を使用して、行末のバックスラッシュを含まない一連の文字を改行のみに変更する置換ステートメントです\n

[^\\]バックスラッシュ以外の任意の1文字に一致する正規表現です。

[^\\]+バックスラッシュ以外の1 つ以上の文字に一致する正規表現です。

[^\\]+$バックスラッシュ以外の1 つ以上の文字に一致し、その後に行末が続く正規表現です。

于 2012-05-02T03:10:57.627 に答える
3

正規表現を使用することは機能するかもしれませんが、この目的のために設計されたモジュールを使用することは、一般的に、より良い考えです。File::BasenameまたはFile::Spec、この目的に適したコアモジュールです。

コード:

use strict;
use warnings;
use v5.10;

use File::Basename;

say dirname($_) for <DATA>;

__DATA__
d:\snow\dir.txt
d:\snow\history\dir.tff
d:\snow\history\help.jar
d:\winter\show\help.txt
d:\summer\beach\ocean\swimming.txt

出力:

d:\snow
d:\snow\history
d:\snow\history
d:\winter\show
d:\summer\beach\ocean

もちろん、円記号を終了する場合は、円記号を追加する必要があります。

そしてのためにFile::Spec

my ($volume, $dir, $file) = File::Spec->splitpath($path);
my $wanted_path = $volume . $dir;  # what you want

これらの2つのモジュールは、長い間コアディストリビューションの一部であり、これは素晴らしいメリットです。

于 2012-05-02T04:20:22.150 に答える
0

このワンライナーでもできます

perl -pe s /\\\\\w+\.\w+$// test.csv > Output.txt

\w+\.\w+$パスの末尾にある拡張子を持つファイル名に一致します

于 2012-05-02T03:48:57.983 に答える
0

これを Python で行う 1 つの方法を次に示します。

python -c 'import sys,re;[sys.stdout.write(re.sub("[^\\\]+$","\n",l))for l in sys.stdin]' < in.txt > out.txt

Perl ソリューションよりも少し冗長であることは認めます。

于 2012-05-02T06:05:54.883 に答える