8

複数行の文字列を一度に 1 行ずつ処理するための適切な PBP 承認済みの方法を見つけようとしています。多くの Perl コーダーは、複数行の文字列をファイル ハンドルとして扱うことを提案しています。次に、厳密な参照が使用されている間は文字列をシンボルとして使用できないという警告がコンパイラから表示されます。

問題の簡単な実例を次に示します。

#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 行目は「open $ResultsHandle, '<', \$return;」です。ちなみにライン。Perl のベスト プラクティスでは strict を使用する必要があるため、複数行の文字列を一度に 1 行ずつ処理することを PBP はどのように期待していますか? SO コミュニティからの提案はありますか?

ありがとう!

4

7 に答える 7

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

于 2009-09-18T16:03:40.623 に答える
7

より簡潔な PBP の方法は、次のようにopenを使用することです。

open my $ResultsHandle, '<', \$return;

これにより、以前の「my $Resultshandle;」の必要がなくなります。宣言し、出くわした厳密な警告が発生するのを回避します。

于 2009-09-18T16:15:24.423 に答える
4

正規表現をイテレータとして使用することもできます:

my $data = q{Hello
This
Is
A
Test};

while( $data =~ /(.+)$/mg) {
    print "line is '$1'\n";
}

これは、文字列を表すファイルハンドルを使用する場合に比べて、やや複雑ではありません。

于 2009-09-18T17:00:07.593 に答える
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
    }
}
于 2009-09-18T15:57:58.133 に答える
2

変化する

my $ResultsHandle = "";

my $ResultsHandle;
于 2009-09-18T16:02:02.950 に答える
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
}
于 2016-12-08T09:33:20.947 に答える
0

"dir" コマンドからのパイプを使用してファイルハンドルを開きます。

例えば

open my $FOO, "dir|" or die "Can not run 'dir': $!";
于 2009-09-18T16:00:22.003 に答える