【'20/5/23追記】配列から特定条件「以降」の要素をgrepで取り出す

`grep`は本来、条件に合う要素**だけ**を配列から取り出す。
でも頑張ればそれだけじゃないこともできるっぽい。

ということで。

```perl
@arr1 = qw/pikachu kairyu yadoran pijon/;
@arr2 = qw/kodakku koratta zubatto gyaroppu/;
@arr3 = qw/sandasu menokurage/;
```

このような文字列配列から、"k"で始まる要素**以降**の要素を`grep`で取り出してみる。

```perl:grep_after.pl
#!/usr/local/bin/perl
use strict;
use warnings;

my @arr1 = qw/pikachu kairyu yadoran pijon/;
my @arr2 = qw/kodakku koratta zubatto gyaroppu/;
my @arr3 = qw/sandasu menokurage/;

sub after_k
{
	print $_[0], "\n";
	@_ = eval $_[0];	# 文字列を変数名として使用（printで変数名を表示したかっただけ）
	print "@_\n";

	my $flg = 0;
	@_ = grep { $flg = /^k/ ? 1 : $flg } @_;	# kで始まる要素「以降」の要素を取り出す
	# 【2020/5/23】更に簡潔になる追記あり（上記コードは追記未適用）
	print "@_\n";
	print 'flg: ', $flg, "\n\n";
}

after_k('@arr1');
after_k('@arr2');
after_k('@arr3');
```

実行結果：

```
@arr1
pikachu kairyu yadoran pijon
kairyu yadoran pijon
flg: 1

@arr2
kodakku koratta zubatto gyaroppu
kodakku koratta zubatto gyaroppu
flg: 1

@arr3
sandasu menokurage

flg: 0

```

​
もちろんここがミソ。

```perl
my $flg = 0;
@_ = grep { $flg = /^k/ ? 1 : $flg } @_;	# kで始まる要素名「以降」の要素を取り出す
```

"k"で始まる要素が来た時にだけフラグを立て、それ以外ではフラグを維持する、という動きを三項演算子でやった。

​
ちなみに最初はこうしていた。

```perl
grep { $flg = /^k/ ? 1 : $flg; $flg > 0 } @_;
```

しかし、Perlでは`0`は偽／`1`は真になるので、この事例ならあえて`> 0`と明示せずともこれで良いのでは？ と思い…

```perl
grep { $flg = /^k/ ? 1 : $flg; $flg } @_;
```

しかし、そんな風に変数をそのまま真偽として渡すなら、わざわざ別途真偽の形にせずともその前で既に`$flg =`の形で取り沙汰してるんだからそれで代えられるのでは？ と思い…

```perl
grep { $flg = /^k/ ? 1 : $flg } @_;
```

というわけで結局こうなったのでした。

​
他にも`map`と組み合わせたりハッシュの何たらを利用したりみたいな方法もありそうだけど、ひとまずこれで。
~~（ハッシュのことがよくわかってないなんて言えない）~~

---

**【2020/5/23 追記】**

三項演算子の分岐先が単なる真偽なら、もう[短絡評価](https://perldoc.jp/docs/perl/perlop.pod#C-style32Logical32Or) `||` で十分だった…。

```perl
grep { $flg = /^k/ || $flg } @_;
```

なお、Perlに真偽値型みたいなものは存在せず、比較演算子とかが生み出す「真」は具体的には `1` を返す。
これはパターンマッチ判定でも同様で、一致した際に返ってくるのは単なる `1` であり、決して文字列の一致部分とか $n$ 文字目を指す数値とかではない。

```perl
my $v0 = 'a' eq 'a';        # 1
my $v1 = 'abc' =~ /b|c/;    # 1
my $v2 = 'abc' =~ /(b|c)/;  # 1
my $v3 = 'abc' =~ /b|c/g;   # 1
print "$v0, $v1, $v2, $v3";
# -> 1, 1, 1, 1
```

<details><summary>※ ただし上記は**スカラコンテキスト**の話であり、**リストコンテキスト**では異なる。今回は無関係なので畳んどくけど…。</summary><div>

- [Perl の演算子と優先順位 > 正規表現のクォート風の演算子 - perldoc.jp](https://perldoc.jp/docs/perl/perlop.pod#Regexp32Quote-Like32Operators)：
    - `/g オプションが使われなかった場合、リストコンテキストでの m// はパターンの中の括弧で括られた部分列にマッチしたもので構成されるリストを返します。` …中略… `パターンに括弧がない場合は、返り値は成功時はリスト (1) です。`
    - `/g 修飾子は` …中略… `リストコンテキストでは、正規表現内の括弧付けされたものにマッチした部分文字列のリストが返されます。括弧がなければ、パターン全体を括弧で括っていたかのように、すべてのマッチした文字列のリストが返されます。`

つまりこう。

```perl
my @a1 = 'abc' =~ /b|c/;    # (1)
my @a2 = 'abc' =~ /(b|c)/;  # ('b')
my @a3 = 'abc' =~ /b|c/g;   # ('b', 'c')
sub j { return join ', ', @_ }
print join(' / ', j(@a1), j(@a2), j(@a3));
# -> 1 / b / b, c
```

そして今回は `$flg = /^k/ || $flg` というスカラ変数への代入なので無関係。
</div></details>

故に、追記後のコードによる「実行結果：」は、`print 'flg: ', $flg` の部分も含めて追記前と全く変わらない。

**【追記ここまで】**

---

余談。
配列を`print`する際、以下が全部違う結果になったのでビビった。

```perl
#!/usr/local/bin/perl
use strict;
use warnings;

my @arr1 = qw/pikachu kairyu yadoran pijon/;

print "@arr1\n";
print @arr1, "\n";
print @arr1."\n";
```

実行結果：

```perl
pikachu kairyu yadoran pijon
pikachukairyuyadoranpijon
4
```