正規表現パターンの場合、&&論理演算子はawkでは機能しません。

正規表現パターンの場合、&&論理演算子はawkでは機能しません。

少し奇妙に見えるのは、&&の論理演算子が||の論理演算子とは異なり、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

無効な演算子接続とその意味を想定しています。テストケースに番号を付けます。

  1. $0 ~/[Ss]ystem/「$0 が /RE/」と一致していることを確認してください。条件は|| /puls/テストでさえありません。全体の条件が真であることが知られているので、「短絡」されています。

  2. &&両方の条件がtrueで、1行だけが一致することを確認してください。

  3. 結合されたRE(2つの選択肢を含む|)は2つの行と一致します。

  4. これは含まれているストレージラインと一致しますSystem

  5. これは何も一致しません。配列に格納されている行をテストしますが、 "/puls/"は$ 0の値をテストします。後ろにファイルの終わりを実行しました。 k1[i]を参照しません。 $ 0にはまだファイルの最後の行が含まれています。入力ファイル全体の終わりにそのような行がないとします。両方の条件を満たす必要&&があるため、一致する行はありません。

  6. (5)の繰り返しである。

  7. (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 $0printと同じで、ジョブがデフォルトの{ print }ジョブなので、次のようになります。

awk '/[Ss]ystem/ && /puls/' /etc/passwd

あなたの最初の主張「&&うまくいきませんが||うまくいきます」が間違っています。

これは「パターンAの場合そしてパターンBがこの入力ラインに表示されます。」:

awk '/[Ss]ystem/ && /puls/' /etc/passwd

これは「パターンAの場合またはパターンBがこの入力ラインに表示されます。」:

awk '/[Ss]ystem/ || /puls/' /etc/passwd

関連情報