我的问题可能很简单,但我是一个完整的新手.我想搜索特定短语的多个文本文件的内容,然后在屏幕上显示查找的行.我已经学会了如何处理单个文件.例如,如果我想搜索一个单词,请在F的根目录中名为"wyvern.txt"的文本文件中说"Okay".以下代码有效:
#!/usr/bin/perl
$file = 'F:\wyvern.txt';
open(txt, $file);
while($line = <txt>) {
print "$line" if $line =~ /Okay/;
}
close(txt);
Run Code Online (Sandbox Code Playgroud)
但是,如果我想在两个文本文件中搜索相同的短语,分别说"wyvern"和"casanova",或者如何在F的根目录中的"novels"目录中查找所有文件,该怎么办?
任何帮助将不胜感激.提前致谢
麦克风
编辑:
哈哈,我终于想出了如何搜索目录中的所有文件以进行模式匹配:)以下代码效果很好:
#!/usr/bin/perl
@files = <F:/novels/*>;
foreach $file (@files) {
open (FILE, "$file");
while($line= <FILE> ){
print "$line" if $line =~ /Okay/;
}
close FILE;
}
Run Code Online (Sandbox Code Playgroud) 说,我有一行包含以下字符串:
"$tom" said blah blah blash. "$dick" said "blah blah blah". "$harry" said blah blah blah.
我想提取
"$dick" said "blah blah blah"
我有以下代码:
my ($term) = /(".+?" said ".+?")/g;
print $term;
Run Code Online (Sandbox Code Playgroud)
但它给了我超过我需要的东西:
"$tom" said blah blah blash. "$dick" said "blah blah blah"
我尝试使用非捕获的parens将我的模式整体分组:
my ($term) = /((?:".+?" said ".+?"))/g;
Run Code Online (Sandbox Code Playgroud)
但问题仍然存在.
我重新阅读了学习Perl的Nongreedy Quantifiers部分,但到目前为止我无处可去.
感谢您提供的任何指导,您可以慷慨地提供:)
这是一个新手问题,但我希望我能尽可能清楚地表达我的问题.
我正在尝试用C++进行模式匹配.
我从这里下载了WinRE 版本的PCRE,并将下载的pcre3.dll和pcreposix3.dll文件放入Dev-CPP的lib文件夹(我使用的是Bloodshed Dev-C++ 4.9.9 IDE).
我还下载了一个pcrecpp.h头文件,并将它放在同一个目录中,我正在编写以下代码(实际上并没有写.我正在处理一个名为PCRE-Perl Compatible Regular Express的PDF教程中的示例代码).
但我无法让它发挥作用.代码如下:
#include <iostream>
#include <string>
#include <pcrecpp.h>
using namespace std;
int main()
{
int i;
string s;
pcrecpp::RE re("(\\w+):(\\d+)");
if (re.error().length() > 0) {
cout << "PCRE compilation failed with error: " << re.error() << "\n";
}
if (re.PartialMatch("root:1234", &s, &i))
cout << s << " : " << i << "\n";
}
Run Code Online (Sandbox Code Playgroud)
当我编译代码时,Dev-C++给了我很多错误,包括:"`pcrecpp'尚未声明"和"RE"未声明.
我该如何处理下载的文件并修复我的问题?或者有什么明显的东西让我失踪?
我已经知道如何将文件的非utf8编码内容逐行转换为UTF-8编码,使用类似下面的代码:
# outfile.txt is in GB-2312 encode
open my $filter,"<",'c:/outfile.txt';
while(<$filter>){
#convert each line of outfile.txt to UTF-8 encoding
$_ = Encode::decode("gb2312", $_);
...}
Run Code Online (Sandbox Code Playgroud)
但我认为Perl可以直接将整个输入文件编码为UTF-8格式,所以我尝试了类似的东西
#outfile.txt is in GB-2312 encode
open my $filter,"<:utf8",'c:/outfile.txt';
Run Code Online (Sandbox Code Playgroud)
(Perl说像"utf8"\ xD4"没有映射到Unicode")
和
open my $filter,"<",'c:/outfile.txt';
$filter = Encode::decode("gb2312", $filter);
Run Code Online (Sandbox Code Playgroud)
(Perl在未打开的文件句柄上说"readline()!"
它们不起作用.但有没有办法直接将输入文件转换为UTF-8编码?
更新:
看起来事情并不像我想象的那么简单.我现在可以以环形方式将输入文件转换为UTF-8代码.我首先打开输入文件,然后将其内容编码为UTF-8,然后输出到新文件,然后打开新文件以进行进一步处理.这是代码:
open my $filter,'<:encoding(gb2312)','c:/outfile.txt';
open my $filter_new, '+>:utf8', 'c:/outfile_new.txt';
print $filter_new $_ while <$filter>;
while (<$filter_new>){
...
}
Run Code Online (Sandbox Code Playgroud)
但这是太多的工作,它比简单地逐行编码$ filter的内容更麻烦.
我的部分代码是这样的:
while(1){
my $winmm = new Win32::MediaPlayer;
$winmm->load('1.mp3'); $winmm->play; $winmm->volume(100);
Do Some Stuff;
last if some condition is met;
}
Run Code Online (Sandbox Code Playgroud)
问题是:当我在while循环中的Do Some Stuff阶段时,我希望音乐始终打开.但是音乐的长度很短,在我进入下一个阶段之前它会完全停止,所以我希望音乐重演,但Win32 :: Mediaplayer模块似乎没有重复模式,所以我想为音乐播放部分做一个无限循环.像这样:
while(1){
my $winmm = new Win32::MediaPlayer;
$winmm->load('1.mp3'); $winmm->play; $winmm->volume(100);
}
while(2){
Do some stuff;
last if some condition is met
}
Run Code Online (Sandbox Code Playgroud)
但根据我目前的Perl知识,如果我在while(1)部分,我永远不会去while(2)部分.即使它涉及到嵌套循环,我也必须做一些事情来突破内部循环,然后再转到外部循环的其他部分.
我的问题的答案"我们可以在Perl中同时运行两个非嵌套循环吗?" 可能是NO,但我认为有一些方法可以处理这种情况.如我错了请纠正我.
一如既往地感谢任何意见/建议:)
UPDATE
我非常感谢大家的帮助.谢谢:)所以我的问题的答案是肯定的,而不是否定的.我很高兴我已经学会了如何使用fork()和线程来解决一个真正的问题:)
我已经完成了一个小实验,如下所示,看起来while循环比Perl中的for循环更快.但由于实验相当粗糙,而且主题可能比看上去复杂得多,我想听听你对此有何看法.一如既往地感谢任何意见/建议:)
在以下两个小脚本中,我分别尝试while和for循环来计算100,000的阶乘.具有while循环的那个用了57分17秒完成,而for循环等效花了1小时7分54秒.
具有while循环的脚本:
use strict;
use warnings;
use bigint;
my $now = time;
my $n = shift;
my $s = 1;
while(1){
$s *= $n;
$n--;
last if $n==2;
}
print $s*$n;
$now = time - $now;
printf("\n\nTotal running time: %02d:%02d:%02d\n\n", int($now / 3600),
int(($now % 3600) / 60), int($now % 60));
Run Code Online (Sandbox Code Playgroud)
有for循环的脚本:
use strict;
use warnings;
use bigint;
my $now = time;
my $n =shift;
my $s=1;
for (my $i=2; $i<=$n;$i++) {
$s = $s*$i;
}
print $s;
$now …Run Code Online (Sandbox Code Playgroud) 假设file1看起来像这样:
bye bye hello thank you
而file2看起来像这样:
chao hola gracias
所需的输出是这样的:
bye bye chao hello hola thank you gracias
我自己已经提出了五种不同的方法来解决这个问题.但我认为必须有更多的方法,可能更简洁,更优雅的方式,我希望我能学到更多很酷的东西:)
以下是我迄今为止所尝试的内容,基于我从之前问题的许多解决方案中学到的内容.此外,我正试图消化或内化我从Llama书中获得的知识.
代码1:
#!perl
use autodie;
use warnings;
use strict;
open my $file1,'<','c:/file1.txt';
open my $file2,'<','c:/file2.txt';
while(defined(my $line1 = <$file1>)
and defined(my $line2 = <$file2>)){
die "Files are different sizes!\n" unless eof(file1) == eof(file2);
$line1 .= $line2;
$line1 =~ s/\n/ /;
print "$line1 \n";
}
Run Code Online (Sandbox Code Playgroud)
代码2:
#!perl
use autodie;
use warnings;
use strict;
open my $file1,'<','c:/file1.txt';
my @file1 = <$file1>;
open …Run Code Online (Sandbox Code Playgroud) 我有一个非常简单的字典应用程序,可以搜索和显示.它是用Win32::GUI模块构建的.我将该字典所需的所有纯文本数据放在该__DATA__部分下.该脚本本身非常小,但该__DATA__部分下的所有内容,其大小达到30 MB.为了与我的朋友分享工作,然后我使用PAR::Packer具有最高压缩级别9 的模块的PP实用程序将脚本打包到一个独立的可执行文件中,现在我有一个大小相当的单文件字典应用程序17MB
但是,尽管我对单文件脚本的想法非常满意,但是在脚本的DATA部分下放置如此大量的文本数据并不合适.首先,当我尝试在Padre中打开脚本时(Notepad ++没问题),我收到的错误是:
Can't open my script as the script is over the arbitrary file size limit which is currently 500000.
我的问题:
如果我将DATA部分下的所有内容移到单独的文本文件中,除了消除Padre的文件打开问题之外,它是否带给我额外的好处?
如果我这样做,我该怎么做才能减小单独文件的大小?拉链并在搜索和显示时解压缩?
人们通常如何格式化字典应用程序所需的文本数据?
有任何意见,想法或建议吗?总是如此谢谢:)
当我使用FLV::Info模块从多个FLV文件中提取元数据或合并多个FLV文件时,我经常收到"标签大小太小"错误,然后模块将拒绝工作.三年前有人在这里发布了一个错误报告,但似乎没有修复.
好吧,最近我发现如果我只是在Tag.pm中注释掉以下代码行,这是一个FLV::Info依赖模块,如下所示:
=pod
if ($datasize < 11)
{
die "Tag size is too small ($datasize) at byte " . $file->get_pos(-10);
}
=cut
Run Code Online (Sandbox Code Playgroud)
FLV::Info 然后将按预期方便地完成工作.
我不确定这是一个非常愚蠢的问题,但我感到很好奇:
是否有一种简单的方法可以在不修改原始.pm文件的情况下更改已加载模块中的几行代码?
有什么想法,建议或意见吗?总是如此谢谢:)
UPDATE
非常感谢@Shwern.你的答案非常令人满意:)还要感谢@DVK的建议和"猴子补丁"一词和@brian的书籍推荐.
这是我对样本FLV文件测试的反馈,如果我使用原始模块而不对其执行任何操作,则会导致"标记大小太小"错误.
"eval it back"方法解决了这个问题
use FLV::Info;
use Data::Dump::Streamer;
my $original = FLV::Tag->can("parse");
my $code = Dump($original)->Out;
#$code =~ s{\Qif ($datasize < 11)\E}{if (0)}; #This somehow won't work
$code =~ s{die "Tag}{warn "Tag}; #Let it warn but not die
no warnings 'redefine';
*FLV::Tag::parse = …Run Code Online (Sandbox Code Playgroud) 根据Bi提出的相关问题,我已经学会了如何打印匹配的线以及它下方的线.代码看起来很简单:
#!perl
open(FH,'FILE');
while ($line = <FH>) {
if ($line =~ /Pattern/) {
print "$line";
print scalar <FH>;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我在谷歌搜索了一个不同的代码,可以打印匹配的行与它们正上方的行.部分适合我的目的的代码是这样的:
#!perl
@array;
open(FH, "FILE");
while ( <FH> ) {
chomp;
$my_line = "$_";
if ("$my_line" =~ /Pattern/) {
foreach( @array ){
print "$_\n";
}
print "$my_line\n"
}
push(@array,$my_line);
if ( "$#array" > "0" ) {
shift(@array);
}
};
Run Code Online (Sandbox Code Playgroud)
问题是我仍然无法弄清楚如何一起做这些.似乎我的大脑正在关闭.有没有人有任何想法?
谢谢你的帮助.
更新:
我觉得我有点感动.你们这么有帮助!也许有点偏离主题,但我真的觉得有更多的冲动.
我需要一个Windows程序,能够搜索多个文件的内容并显示相关信息,而无需单独打开每个文件.我尝试使用谷歌搜索和两个应用程序,代理Ransack和Devas,已证明是有用的,但它们只显示包含匹配查询的行,我想要查看相邻的行.然后,即兴创作一个程序的想法突然出现在我脑海中.多年前,我对Perl脚本印象深刻,可以生成维基百科的Tomeraider格式,这样我就可以轻松地在我的Lifedrive上搜索Wiki,而且我也在网上读到了Perl很容易学习的地方,特别是像我这样的人没有任何编程语言的经验.然后我几天前就开始自学Perl了.我的第一步是学习如何完成与"Agent Ransack"相同的工作,并且使用Perl证明它并不那么困难.我首先学习了如何搜索单个文件的内容并通过修改标题为"Perl by Example"的书中使用的示例来显示匹配的行,但我被困在那里.我对如何处理多个文件变得完全无能为力.书中没有找到类似的例子,也可能是因为我太不耐烦了.然后我再次尝试谷歌搜索并被带到这里,我问了我的第一个问题"如何在Perl中搜索多个文件中的字符串模式?" 在这里,我必须说这个论坛是血腥的真棒;).然后我查看了更多示例脚本,然后我昨天提出了以下代码,它很好地满足了我原来的目的:
代码如下:
#!perl
$hits=0;
print "INPUT YOUR QUERY:";
chop ($query = <STDIN>);
$dir …Run Code Online (Sandbox Code Playgroud) perl ×9
c++ ×1
dictionary ×1
for-loop ×1
loops ×1
module ×1
pcre ×1
performance ×1
regex ×1
simultaneous ×1
unicode ×1
utf-8 ×1
while-loop ×1