Bashスクリプト:別の行で「AND」条件を使用してテキストファイルを読み取る

Bashスクリプト:別の行で「AND」条件を使用してテキストファイルを読み取る

「AND」条件を使用して単純なbashスクリプトを作成しましたが、機能しません。

#!/bin/bash

cat log3.txt | \
while read -r LINE
do
  if [[ $LINE =~ Host ]] && [[ $LINE =~ denied ]]  ; then echo $LINE;
fi
done

log3.txtの内容です。

Host: abcd.com
Access denied

OR条件を使用するとうまく機能しますが、AND条件を使用したいので、ログに「Host」と「Access Denied」の両方の文字列が含まれている場合は、出力が表示されます。

ベストアンサー1

ループの1つの反復では、while値は$LINE同時に存在できません。Host そして denied。ファイルのデータを考慮すると、これは不可能です。だから、出力が得られないのです。

これら2つの単語に一致するファイルのすべての行を表示するにはHost または deniedgrep代わりに以下を使用してください。

grep -wF -e 'Host' -e 'Access denied' <log3.txt

ここで使用されているオプションは、正規表現の一致()ではなく文字列比較を実行し、部分文字列()の-F代わりに完全な単語と一致することを保証します。-w2 つのクエリ文字列が与えられたら、-e次を含むすべての行を取得します。どのこれら。

両方の単語がファイルに表示される場合にのみ、両方の単語を含む行のみを表示するより高度なクエリを実行するには、プログラムを使用して実行できますawk

awk '/Host/ { hostline=$0 } /Access denied/ { deniedline=$0 }
     END { if ((hostline != "") && (deniedline != ""))
               print hostline; print deniedline; }' <log3.txt

ここで文字列と一致する行を見つけたら、Host文字列と同じように保存しますAccess denied。最後に、両方の文字列に何かが含まれている場合はそれを印刷します。

やや同等のシェルコードで:

#!/bin/sh

while IFS= read -r line; do
    case $line in
        *Host*)
           hostline=$line   ;;
        *"Access denied"*)
           deniedline=$line ;;
    esac
done <log3.txt

if [ -n "$hostline" ] && [ -n "$deniedline" ]; then
    printf '%s\n%s\n' "$hostline" "$deniedline"
fi

case ... esacここでは、読み取ったデータを一致させるステートメントを使用します。使用されるパターンは、正規表現ではなくファイル名のワイルドカードパターンです。

関連:

おすすめ記事