1

grep を 2 回使用したい:

1) tsv ファイルから 2 次元配列を取得しました。grep を使用して行を検索し、次の列の内容をコピーしたいと思います。

例えば:

ファイル:

red     cat
blue    dog

コード:

open (LIST, "file.tsv");
my @list = <LIST>;
my @grepd = grep /blue/ @list;
print @grepd;

その結果、perl は印刷します"blue dog"。私は彼に印刷のみを依頼します"dog"

2) リストがあります。grep を使用してフレーズを検索し、その横にあるオブジェクトをコピーしたいと考えています。

例えば:

my @list = ('red', 'cat','blue', 'dog');
my @grepd = grep /red/ @list;
print @grepd;

その結果、perl が印刷するので、代わりに"red"彼に印刷させることはできますか? "cat"または、より一般的には、クエリ オブジェクトの隣にあるオブジェクトを出力しますか?

どうもありがとう!

4

2 に答える 2

1

「<em>grep次の要素を指定できますか?」という質問について、それを行う関数を作成してみましょう。

まず、最後のインデックスを除くすべてのインデックスをループします。インデックスの要素が条件を満たすと、次の要素が記憶されます。これは次のように書くことができます:

my @input = ...;
my @output = map  { $input[$_ + 1]                 }  # get the next element
             grep { $input[$_] =~ /some condition/ }  # grep all interesting indices
             0 .. $#input - 1;  # all indices but the last

または同等:

my @input = ...;
my @output;

for my $i (0 .. $#input - 1) {
  push @output, $input[$i + 1] if $input[$i] =~ /some condition/;
}

これを関数に抽象化します。そのために、コールバック(または無名関数) を最初の引数として取ります。$_次に、現在の要素に設定してこの関数を呼び出します。その関数の呼び出し元を汚染しないように、設定する前にその変数をローカライズする必要があります。

sub grepnext (&@) {
  my $callback = shift;
  # input is @_
  my @out;
  for my $i (0 .. $#_ - 1) {
    # localize $_ and set it to the current element
    local $_ = $_[$i];
    push @out, $_[$i + 1] if $callback->();
  }
  return @out;
}

今できること:

my @after_red = grepnext { /red/ } qw(red cat blue dog);

grepnext上記のように呼び出せるように宣言しました。これは(&@) プロトタイプを使用します。プロトタイプは、特定の状況下で関数呼び出しの解析を変更できるようにする機能です。これらは非常に強力であり、通常は使用しないでください。名前付きパラメーターとは関係がなく、引数の検証には使用できません。また、サブルーチンは、それを呼び出す前に宣言する必要があります。

プロトタイプがなければ、次のフォームを使用する必要があります。

my @after_red = grepnext sub{ /red/ }, qw(red cat blue dog);

いずれにせよ、@after_redには 1 つの要素が正しく含まれるようになりまし"cat"た。

于 2013-10-20T10:52:52.193 に答える