質問に狭く答えるために、そのコード行で未定義値の警告を防ぐことができます
if (defined $i && defined $arrayOld[$i]
&& ($arrayOld[$i] =~ /-(.*)/ || $arrayOld[$i] =~ /\#(.*)/))
{
...;
}
つまり、$i
または式のいずれかを評価する$arrayOld[$i]
と、未定義の値になる可能性があります。&&
との優先順位の違いにより、上記のように追加の括弧が必要になることに注意してください||
。前者はより厳密に結合します。質問の特定のパターンについては、パターンを 1 つの正規表現に結合することでこの優先順位の問題を回避できますが、これは一般的なケースでは難しい場合があります。
上記の好ましくないコードは使用しないことをお勧めします。Perl が作業を行い、はるかに読みやすい、問題に対する洗練された解決策を確認するために読んでください。
思い返す
以前の質問の少し広い文脈から、$i
はループ変数であり、構築により確実に定義されるため、テスト$i
はやり過ぎです。あなたのコードはやみくもに から要素を引っ張ってきますが@arrayOld
、Perl は喜んで義務付けます。何もない場合は、未定義の値が返されます。
この種の 1 つずつのぞき見や突っ込みは、C プログラムでは一般的ですが、Perl では、ほとんどの場合、アルゴリズムをよりエレガントに表現できるという危険信号です。以下の完全に機能する例を考えてみましょう。
作業デモンストレーション
#! /usr/bin/env perl
use strict;
use warnings;
use 5.10.0; # given/when
*FILEREAD = *DATA; # for demo only
my @interesting_line = (qr/-(.*)/, qr/\#(.*)/);
$/ = ""; # paragraph mode
while(<FILEREAD>) {
chomp;
my @arrayOld = split /\n/;
my @arrayNewLines;
for (1 .. @arrayOld) {
given (shift @arrayOld) {
push @arrayNewLines, $_ when @interesting_line;
push @arrayOld, $_;
}
}
print "\@arrayOld:\n", map("$_\n", @arrayOld), "\n",
"\@arrayNewLines:\n", map("$_\n", @arrayNewLines);
}
__DATA__
#SCSI_test # put this line into @arrayNewLines
kdkdkdkdkdkdkdkd
dkdkdkdkdkdkdkdkd
- ccccccccccccccc # put this line into @arrayNewLines
フロントの問題
この線
use 5.10.0;
Perl のgiven
/ when
switch ステートメントを有効にします。これにより、特定の入力行を取得する配列を決定する優れた方法が得られます。
コメントが示すように
*FILEREAD = *DATA; # for demo only
これは、このスタック オーバーフローのデモンストレーションを目的としています。実際のコードでは、open FILEREAD, ...
. 質問からの入力を Perl のDATA
ファイルハンドルに配置すると、コードと入力を 1 つの自己完結型ユニットに表示できます。その後、エイリアスFILEREAD
を作成するDATA
ので、コードの残りの部分は問題なくあなたのものにドロップされます。
メインイベント
加工の肝は
for (1 .. @arrayOld) {
given (shift @arrayOld) {
push @arrayNewLines, $_ when @interesting_line;
push @arrayOld, $_;
}
}
defined
チェックや明示的な正規表現の一致さえないことに注意してください! $i
またはありません$arrayOld[$i]
!どうしたの?
@arrayOld
現在の段落のすべての行を含めることから始めて、 の興味深い行で終了し、@arrayNewLines
他のすべては にとどめたいとします@arrayOld
。上記のコードは@arrayOld
withから次の行を取り出しshift
ます。行が興味深い場合はpush
、 の最後に移動し@arrayNewLines
ます。それ以外の場合は、 の最後に戻し@arrayOld
ます。
ステートメント修飾子when @interesting_line
は、 のトピックとの暗黙的なスマート マッチを実行しgiven
ます。「スマート マッチングの詳細」で説明したように、配列に対してスマート マッチングを行うと、Perl は暗黙的にそれをループし、最初の一致で停止します。この場合、配列@interesting_line
には、移動先の行に一致するコンパイル済み正規表現が含まれています@arrayNewLines
。$_
( のおかげで)現在の行given
がこれらのパターンのいずれとも一致しない場合は、 に戻り@arrayOld
ます。
前述のプロセスを正確にscalar @arrayOld
1 回、つまり現在の段落の各行に対して 1 回実行します。このようにして、すべてを正確に 1 回処理し、現在の配列インデックスがどこにあるのかについて煩雑な簿記について心配する必要がなくなります。@arrayOld
その多くの s の後に残っているものはすべて、その上に編集して戻しshift
た行でなければなりませんpush
。これは、入力で発生した順序での興味深い行ではありません。
サンプル出力
質問の入力の場合、出力は
@arrayOld:
kdkdkdkdkdkdkdkd
dkdkdkdkdkdkdkdkd
@arrayNewLines:
#SCSI_test # この行を @arrayNewLines に入れます
- ccccccccccccccc # この行を @arrayNewLines に入れます