2

perl を使用してこの正規表現コードを修正するには、専門家の助けが必要ですか?

私はこのデータファイルを持っています...

__データ__
SCSI - テスト A
cccccccccccccccccc
あああああああああああああ
bbbbbbbbbbbbbbbb

__データ__
SCSI - テスト B
cccccccccccccccccc
あああああああああああああ
bbbbbbbbbbbbbbbb

__データ__
SCSI - テスト-C
cccccccccccccccccc
あああああああああああああ
bbbbbbbbbbbbbbbb

次の出力が欲しい

__データ__
SCSI - テスト A

__データ__
SCSI - テスト B

__データ__
SCSI - テスト-C

__Data__代わりに、 2 つのデータ レコードが欠落しているこの出力を取得しています。

__データ__
SCSI - テスト A
SCSI - テスト B
SCSI - テスト-C

ここでコード..

$/ = "__Data__"; # setting the input separator variable to __Data__

while(<ReadFile>)
{
   $_ =~ s/(SCSI.*test-(A|B|C)?)(.*)/$1/ms;
   print $_;
}
4

4 に答える 4

2

行が で終わることをPerlに伝えている__DATA__ので、取得しています

1: "__Data__"
2: "\nSCSI - test-A\nccc\naaa\nbbb\n\n__Data__"
3: "\nSCSI - test-B\nccc\naaa\nbbb\n\n__Data__"
4: "\nSCSI - test-C\nccc\naaa\nbbb\n"

しかし、あなたはあなたが得ると間違って考えています

1: "__Data__\nSCSI - test-A\nccc\naaa\nbbb\n\n"
2: "__Data__\nSCSI - test-B\nccc\naaa\nbbb\n\n"
3: "__Data__\nSCSI - test-C\nccc\naaa\nbbb\n"

解決:

my $after_data = 0;
while (<>) {
   if (/^__Data__$/) {
      print;
      $after_data = 1;
   }
   elsif ($after_data) {
      print;
      print "\n";
      $after_data = 0;
   }
}

段落モードを使用することもできます。

local $/ = '';
while (<>) {
   print /^(.*\n.*\n)/;
   print "\n";
}
于 2012-05-17T22:27:07.297 に答える
0

段落モードを有効にするには、入力レコード セパレータを空の文字列に設定します。印刷に改行を追加します。

$/ = ""; # paragraph mode

while (<ReadFile>) {
    $_ =~ s/(SCSI.*test-(A|B|C))(.*)/$1/s;
    print "$_\n\n";
}
于 2012-05-17T22:23:20.723 に答える
0

追加してみる

    $\ = $/;

…出力レコード区切りも設定します。

ただし、各レコードの__Data__(各 の最後) に出力されるため、そのようにの最終的な偽のインスタンスになってしまいます。print

または、入力を自分で分割することもできます。

  while (<ReadFile>)
  {   chomp;
      next unless $_ eq '__Data__'; print;
      my $next = <ReadFile>;
      $next =~ s/(SCSI.*text-(A|B|C)?).*/$1/ms;
      print $next;
  }
于 2012-05-17T22:13:11.843 に答える
0

3 つのカテゴリのいずれかに当てはまる行を印刷したいと考えているようです。

  1. __Data__マーカー
  2. SCSI テスト ライン
  3. 空行

Perl の段落モードは、機能すれば便利ですが、脆弱です。段落はシーケンスによって正確"\n\n"に終了しますが、空白を表示しないエディターでは、段落の後に空白ではあるが空ではない行がある場合、これをデバッグするのが難しくなる可能性があります。

あなたの質問に書かれているように、以下のコードはあなたが望む出力を生成します。

#! /usr/bin/env perl

use strict;
use warnings;
use 5.10.0;  # smart matching

*ARGV = *DATA;  # for demo only

my @interesting_line = (qr/^__Data__/, qr/SCSI - test-/, qr/^\s*$/);

while (<>) {
  print if $_ ~~ @interesting_line;
  print "\n" if eof && !eof();
}

__DATA__
__Data__
SCSI - test-A
ccccccccccccccccc
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbb

__Data__
SCSI - test-B
ccccccccccccccccc
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbb

__Data__
SCSI - test-C
ccccccccccccccccc
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbb

実際の使用では、デモ専用とマークされた行を削除してから、コマンド ラインで 1 つまたは複数のデータ ファイルを指定します。おかしな見た目のif eof && !eof()テストは、レコード間に追加のセパレーターをいつ挿入するかを決定しようとします。正確に正しくしたい場合は、より慎重に行う必要があります。

複数のファイルに対する入力の例を以下に示します。

$猫入力1
__データ__
SCSI - テスト A
cccccccccccccccccc
あああああああああああああ
bbbbbbbbbbbbbbbb

__データ__
SCSI - テスト B
cccccccccccccccccc
あああああああああああああ
bbbbbbbbbbbbbbbb

$猫入力2
__データ__
SCSI - テスト-C
cccccccccccccccccc
あああああああああああああ
bbbbbbbbbbbbbbbb

$ ./extract-tests 入力1 入力2
__データ__
SCSI - テスト A

__データ__
SCSI - テスト B

__データ__
SCSI - テスト-C
于 2012-05-26T15:14:24.727 に答える