我正在尝试找出正确的PBP批准方式,一次处理多行字符串。许多Perl程序员建议将多行字符串视为文件句柄,除非你的脚本中有“use strict”,否则它可以正常工作。然后,当编译器使用严格的引用时,您会收到编译器关于无法使用字符串作为符号的警告。
以下是该问题的简单工作示例:
#use strict;
use warnings;
my $return = `dir`;
my $ResultsHandle = "";
my $matchLines = "";
my $resultLine = "";
open $ResultsHandle, '<', \$return;
while (defined ($resultLine = <$ResultsHandle>)) {
if ($resultLine =~ m/joe/) {
$matchLines = $matchLines . "\t" . $resultLine;
}
}
close($ResultsHandle);
print "Original string: \n$return\n";
print "Found these matching lines: \n$matchLines\n";
请注意,“use strict”行已被注释掉。当我在没有使用严格的情况下运行这个脚本时,我得到了我想要的东西:
Original string:
Volume in drive D has no label.
Volume Serial Number is 50D3-54A6
Directory of D:\Documents and Settings\username\My Documents\Eclipse\myTestProject
09/18/2009 11:38 AM <DIR> .
09/18/2009 11:38 AM <DIR> ..
09/18/2009 11:36 AM 394 .project
09/18/2009 11:37 AM 0 joe.txt
09/18/2009 11:37 AM 0 joey.txt
09/18/2009 11:38 AM 0 kurt.txt
09/18/2009 11:43 AM 497 main.pl
09/18/2009 11:38 AM 0 shane.txt
6 File(s) 891 bytes
2 Dir(s) 6,656,188,416 bytes free
Found these matching lines:
09/18/2009 11:37 AM 0 joe.txt
09/18/2009 11:37 AM 0 joey.txt
但这是问题所在。当我取消注释“use strict”行时,我从Perl收到以下警告或错误:
Can't use string ("") as a symbol ref while "strict refs" in use at D:/Documents and Settings/username/My Documents/Eclipse/myTestProject/main.pl line 8.
第8行是“打开$ ResultsHandle,'&lt;',\ $ return;”顺便说一下。因此,由于Perl Best Practices要求我使用严格,PBP如何期望我一次处理一行多行字符串?来自SO社区的任何建议?
谢谢!
答案 0 :(得分:11)
不要初始化$ResultsHandle
:
use strict;
use warnings;
my $return = `dir`;
my $ResultsHandle; # <-- leave undefined
my $matchLines = "";
my $resultLine = "";
open $ResultsHandle, '<', \$return;
while (defined ($resultLine = <$ResultsHandle>)) {
if ($resultLine =~ m/joe/) {
$matchLines = $matchLines . "\t" . $resultLine;
}
}
close($ResultsHandle);
print "Original string: \n$return\n";
print "Found these matching lines: \n$matchLines\n";
如果您在$ResultsHandle
之前未定义open()
,则会使用对文件句柄的引用来填充它。因为你将它设置为一个字符串,open()
假定它应该是一个变量的符号引用 - 而不是use strict
下允许的。
答案 1 :(得分:7)
更简洁的PBP方式是如此使用open:
open my $ResultsHandle, '<', \$return;
这消除了之前“my $ Resultshandle”的需要。声明并避免招致您遇到的严格警告。
答案 2 :(得分:4)
您还可以使用regexp作为迭代器:
my $data = q{Hello
This
Is
A
Test};
while( $data =~ /(.+)$/mg) {
print "line is '$1'\n";
}
与使用表示字符串的文件句柄相比,这稍微复杂一些。
答案 3 :(得分:3)
使用split
将多行字符串转换为单行字符串列表:
my @resultLines = split /\n/, $result; # or /\r\n/ for Windows?
foreach my $resultLine (@resultLines) {
if ($resultLine =~ m/joe/) {
$matchLines
= $matchLines . "\t"
. $resultLine . "\n"; # put \n or \r\n back on the end
}
}
答案 4 :(得分:2)
更改
my $ResultsHandle = "";
到
my $ResultsHandle;
答案 5 :(得分:0)
使用“dir”命令中的管道打开文件句柄。
E.g。
open my $FOO, "dir|" or die "Can not run 'dir': $!";
答案 6 :(得分:0)
分裂的更好结果可以通过以下方式完成:
my $result="LINE1
line2
linE3
";
#attention, /^/m allows properly operate on multiline string using regex
#and ^ is character empty begin all lines
foreach my $resultLine (split /^/m, $result) {
print $resultline; #withount '\n' because it have got
#some checks & operations
}