我一直在使用以下Perl代码从多个文本文件中提取文本。它工作正常。
其中一个输入文件中的几行示例:
Fa0/19 CUTExyz notconnect 129 half 100 10/100BaseTX
Fa0/22 xyz MLS notconnect 1293 half 10 10/100BaseTX
我需要的是精确匹配每一行中的数字(即129
与1293
不匹配)并打印相应的行。
将一系列数字与特定数字相匹配也很好,即匹配2到10但不是11到12到20
#!/perl/bin/perl
use warnings;
my @files = <c:/perl64/files/*>;
foreach $file ( @files ) {
open( FILE, "$file" );
while ( $line = <FILE> ) {
print "$file $line" if $line =~ /123/n;
}
close FILE;
}
感谢您提出建议,但可以使用上面的代码结构吗?
答案 0 :(得分:3)
我建议你看看perldoc perlre
。
你需要锚定你的正则表达式模式。最简单的方法可能是使用\b
,它是字母数字和非字母数字之间的零宽度边界。
#!/perl/bin/perl
use warnings;
use strict;
foreach my $file ( glob "c:/perl64/files/*" ) {
open( my $input, '<', $file ) or die $!;
while (<$input>) {
print "$file $_" if m/\b123\b/;
}
close $input;
}
注意 - 你应该使用三个参数open
和上面的词法文件句柄,因为这是更好的做法。
我还删除了n
模式修饰符,因为它看似多余。
编辑后,给我们一些源数据。我建议解决方案是不使用正则表达式 - 您的源数据看起来是空格分隔的。 (也许那些是标签?)。
所以我建议你最好使用split
并选择你想要的字段,然后用数字进行测试,因为你提到了匹配的范围。这不适合正则表达式,因为它们不理解数字内容。
相反:
while ( <$input> ) {
print if (split)[-4] == 129;
}
注意 - 我在-4
中使用split
,该列表来自列表的 end 。
这是因为第3列包含空格,因此除非我们从数组末尾倒数,否则在空格上拆分会产生错误的结果。使用负索引,我们每次都得到正确的字段。
如果您的数据以制表符分隔,则可以使用chomp
和split /\t/
。或者可能在/\s{2,}/
上拆分以拆分2或更多空格
但是通过选择字段,您可以对其进行数字测试,例如
if $fields[-4] > 100 and $fields[-4] < 200
等
答案 1 :(得分:2)
我希望你没有得到你要求的答案,因为你不熟悉Perl而放弃了最佳实践。询问如何编写丑陋的解决方案是不合适的,因为适当的Perl 超出了您的范围
正如在本网站上反复说过的那样,如果你不知道如何做某份工作,那么你应该聘请知道并付钱给他们工作的人。我所知道的其他职业都没有期望免费完成高质量的工作
以下是您的代码的一些注意事项。无论你在哪里学习过技巧,你都在寻找一个非常过时的资源
你确实有一个根目录perl
,那么你的编译器是/perl/bin/perl
吗?这非常不寻常,并且不需要在Windows中使用 shebang 行
使用use strict
的变量尽可能接近其第一个使用点。出于某种原因,您使用use warnings 'all'
但不使用my
最好将@files
替换为$file
。否则代码不太清楚,因为Perl会重载<c:/perl64/files/*>
运算符
不要将变量名放在双引号内。它最多是不必要的,并可能导致错误。因此glob 'C:/perl64/files/*'
应为<>
始终使用"$file"
的三参数版本,以便第二个参数为开放模式
不要使用全局文件句柄。并且始终测试文件是否已正确打开,如果$file
失败,则会显示包含open
- 原因的消息而导致失败的消息
$!
应该是
open
不要依赖正则表达式模式。在这种情况下,如果您的记录具有固定宽度字段,则open( FILE, "$file" )
似乎是更好的选项,或者open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!}
。在我的解决方案中,我使用了split
&#34;多个空格&#34;,但如果您的真实数据与您显示的不同(制表符分隔?),那么这不会起作用
请注意,unpack
也会与您当前的方法相匹配
此Perl程序过滤您的数据,打印第四个字段split
(由多个空白字符描绘)在数字上等于Fa0/129
当输入为单个文件$lines[3]
时,会显示所显示的输出,其中包含问题中显示的数据
129
splitn.txt
答案 2 :(得分:1)
你的问题不清楚。当你说:
我需要的是准确匹配每行中的数字
这可能意味着一些事情。这可能意味着每行只包含您想要匹配的单个数字。在这种情况下,使用==
可能比使用正则表达式更好。或者它可能意味着你在一行上有很多文字而你只想匹配完整的数字。在这种情况下,您应该使用\b
(&#34;字边界&#34;锚点) - /\b123\b/
。
如果您在问题中更清楚(可能是通过提供样本输入),那么人们就不必猜测您的意思。
您的代码还有几点:
use strict
和use warnings
。open()
的返回值,并对失败采取适当的措施。open()
的3-arg版本。$file
来电中引用open()
。$_
可以简化您的代码。/n
无效。将所有内容放在一起(假设我对您的问题的第二种解释是正确的),您的代码可能如下所示:
#!/perl/bin/perl
use strict;
use warnings;
my @files = <c:/perl64/files/*>;
foreach my $file (@files) {
open my $file_h, '<', $file
or die "Can't open $file: $!";
while (<$file_h>) {
print "$file $_\n" if /\b123\b/;
}
# No need to close $file_h as it is closed
# automatically when the variable goes out
# of scope.
}