少し奇妙に見えるのは、&&の論理演算子が||の論理演算子とは異なり、awk if正規表現パターンでは機能しないことです。効果がある!
注:しかし、&&論理演算子は純粋で単純なawk正規表現モードで動作しますが、その理由は何ですか?
#
#
# cat /etc/passwd|awk '$0 ~/[Ss]ystem/ || /puls/ {print $0}'
dbus:x:81:81:System message bus:/:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
#
#
#
# cat /etc/passwd|awk '$0 ~/[Ss]ystem/ && /puls/ {print $0}'
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
#
#
#
# cat /etc/passwd|awk '$0 ~/[Ss]ystem|puls/ {print $0}'
dbus:x:81:81:System message bus:/:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
#
#
#
# cat /etc/passwd|awk '{k1[NR]=$0}END{for(i=1;i<=NR;i++)if(k1[i] ~/[Ss]ystem/ || /puls/){print k1[i]}}'
dbus:x:81:81:System message bus:/:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
#
#
# cat /etc/passwd|awk '{k1[NR]=$0}END{for(i=1;i<=NR;i++)if(k1[i] ~/[Ss]ystem/ && /puls/){print k1[i]}}'
#
#
# cat /etc/passwd|awk '{k1[NR]=$0}END{for(i=1;i<=NR;i++)if(k1[i] ~/[Ss]ystem/ && /puls/){print k1[i]}}'
#
#
# cat /etc/passwd|awk '$0 ~/[Ss]ystem/ && /puls/ {print $0}'
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
#
#
今少し変わったので、最近の状況は以前よりも奇妙になる可能性があります!
配列変数と論理演算子&&を持つ以下の同じ正規表現パターンが機能するのはなぜですか?
注:正規表現パターンが少なくとも配列変数自体と関連していない場合は、問題のいくつかを説明する必要があります。
#
#
# cat /etc/passwd|awk '{k0[NR]=$0;if(k0[NR] ~/[Ss]ystem/ && /puls/){print k0[NR]}}'
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
#
#
# cat /etc/passwd|awk '{k0[NR]=$0;if(k0[NR] ~/[Ss]ystem/ || /puls/){print k0[NR]}}'
dbus:x:81:81:System message bus:/:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
#
#
# cat /etc/passwd|awk '{k0[NR]=$0;if(k0[NR] ~/[Ss]ystem/ && /puls/){print k0[NR]}}'
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
#
#
答え1
最初の部分では
$0 ~/[Ss]ystem/ && /puls/
暗黙的です
$0 ~/[Ss]ystem/ && $0 ~ /puls/
だから
if(k1[i] ~/[Ss]ystem/ && /puls/)
次のように書く必要があります。
if(k1[i] ~/[Ss]ystem/ && k1[i] ~ /puls/)
- 前者の場合(*)がの最後の行と一致する
可能性/pusl/
が高いです。/etc/passwd
- また参照してください。
man awk
ただし、~
(および!~
)が優先されます。&&
(*)OK、PulseAudio ラインを最後のラインに移動するとマッチングが完了します。
答え2
無効な演算子接続とその意味を想定しています。テストケースに番号を付けます。
$0 ~/[Ss]ystem/
「$0 が /RE/」と一致していることを確認してください。条件は|| /puls/
テストでさえありません。全体の条件が真であることが知られているので、「短絡」されています。&&
両方の条件がtrueで、1行だけが一致することを確認してください。結合されたRE(2つの選択肢を含む
|
)は2つの行と一致します。これは含まれているストレージラインと一致します
System
。これは何も一致しません。配列に格納されている行をテストしますが、 "/puls/"は$ 0の値をテストします。後ろにファイルの終わりを実行しました。 k1[i]を参照しません。 $ 0にはまだファイルの最後の行が含まれています。入力ファイル全体の終わりにそのような行がないとします。両方の条件を満たす必要
&&
があるため、一致する行はありません。(5)の繰り返しである。
(2)の繰り返しです。
答え3
以下は、元の質問の「最新」バージョンを単純化して分解したものです。
cat /etc/passwd|awk '{k0[NR]=$0;if(k0[NR] ~/[Ss]ystem/ && /puls/){print k0[NR]}}'
awk自体がファイルを読み取ることができるので、catはコードに何も追加しません。 (詳しくはGoogle UUOCをご覧ください。)
入力行を配列に保存してから同じステートメントで値をテストすると、何も追加されません(ENDブロックがないため)。したがって、次のように単純化できます。
awk '{if($0 ~/[Ss]ystem/ && /puls/){print $0}}' /etc/passwd
パターンマッチングの使用は~
通常のREと同じであるため、次のように単純化されます。
awk '{if(/[Ss]ystem/ && /puls/){print $0}}' /etc/passwd
an の使用は中if
かっこの外のパターンと同じなので、次のようになります。
awk '/[Ss]ystem/ && /puls/ {print $0}' /etc/passwd
print $0
print
と同じで、ジョブがデフォルトの{ print }
ジョブなので、次のようになります。
awk '/[Ss]ystem/ && /puls/' /etc/passwd
あなたの最初の主張「&&
うまくいきませんが||
うまくいきます」が間違っています。
これは「パターンAの場合そしてパターンBがこの入力ラインに表示されます。」:
awk '/[Ss]ystem/ && /puls/' /etc/passwd
これは「パターンAの場合またはパターンBがこの入力ラインに表示されます。」:
awk '/[Ss]ystem/ || /puls/' /etc/passwd