3

我一直在尝试做一些 perl 正则表达式并且已经碰壁了。我正在尝试对日志文件进行一些数据分析,但遇到了以下问题:

我有一个文件 test.csv,它由来自另一个程序的多个单行条目组成,该程序产生以下布局格式:

  • d:\snow\dir.txt
  • d:\雪\历史\dir.tff
  • d:\snow\history\help.jar
  • d:\winter\show\help.txt
  • d:\summer\beach\ocean\swimming.txt

我想要做的是从路径列表中删除文件名,因此生成的文件将包含:

  • d:\雪\
  • d:\雪\历史\
  • d:\雪\历史\
  • d:\冬季\表演\
  • d:\夏天\海滩\海洋\

我已经把我的头撞到了墙上,并尝试了各种 perl 正则表达式,试图在没有太多运气的情况下删除文件名。由于目录的路径长度不同,所以我碰壁了,我不确定这是否可以在 perl 或 python 中完成。

4

4 回答 4

4

你可以用 Perl 中的一行代码来做到这一点:

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

把它分成几部分:

-p使 Perl 将语句(附带-e)包装在一个while循环中,将该语句应用于输入文件的每一行,并打印结果。

-e给 Perl 一个针对每一行运行的语句。

s/[^\\]+$/\n/是一个替换语句,它使用正则表达式将任何不包括行尾反斜杠的字符序列更改为仅换行符\n

[^\\]是匹配任何非反斜杠的单个字符的正则表达式

[^\\]+是一个正则表达式,匹配一个或多个不是反斜杠的字符

[^\\]+$是一个正则表达式,匹配一个或多个不是反斜杠的字符,后跟行尾

于 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

这两个模块长期以来一直是核心发行版的一部分,这是一个很好的好处。

于 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 中执行此操作的一种方法:

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 回答