3番目に成功したログイン試行のユーザー名を印刷します。

3番目に成功したログイン試行のユーザー名を印刷します。

次のログファイルがありますが、3回目の試みで正常にログインしたユーザーの名前を印刷したいと思います。

cat login.log
user1:failed
user2:failed
user3:success
user1:failed
user2:failed
user4:success
user5:failed
user2:success
user3:failed
user6:success
user1:success
user3:success
user4:success
user4:success
user5:failed
user5:failed
user1:success
user2:failed

予想される出力は次のとおりです。

user1
user2

答え1

努力する

awk -F: '/failed/ { f[$1]++;} /success/ && f[$1]==2 { print ; f[$1]=0 ; }'

どこ

  • -F::区切り文字として使用
  • /failed/ { f[$1]++;}ユーザーログイン失敗回数の計算
  • /success/ && f[$1]==2 { print $1; f[$1]=0 ; }条件に応じて結果を印刷します。

コメントに従って特別な名前がある場合(読みやすくするために改行)

awk -F: '$2 == "failed" { f[$1]++;} 
         $2 == "success" && f[$1]==2 { print ; f[$1]=0 ; }'

答え2

単純なbashのみの解決策:行を繰り返し、失敗するたびにカウンターを増やし、成功するたびにそのカウンターの値を確認し、必要な値と一致するといくつかの出力を生成します。sort -u最後のボーナスは、すべての出現ではなく、一致するユーザーのみを出力することです。可能な改善方法は、成功時にカウンタをゼロにリセットすることです。ただし、これを行う方法を直接理解できるはずです。

$ unset FAILURES  # In case you've already tried inthis shell
$ declare -A FAILURES
$ while IFS=: read USERNAME STATUS ; do [ "$STATUS" == "failed" ] && (( FAILURES[$USERNAME] += 1)); [ "$STATUS" == "success" -a "0${FAILURES[$USERNAME]}" -eq 2 ] && echo $USERNAME because status is $STATUS and failures is ${FAILURES[$USERNAME]}; done < login.log | sort -u
user1 because status is success and failures is 2
user2 because status is success and failures is 2
$

答え3

誰がログインしたかを追跡し、この極端なケースと一致しないようにします。

joe:success
joe:failed
joe:failed
joe:success
awk -F: '
    $2 == "failed" {fail[$1]++} 
    $2 == "success" && !loggedin[$1] {
        if (fail[$1] == 2) print $1
        loggedin[$1] = 1
    }
' login.log

以前にログインしたかどうかにかかわらず、2回連続失敗した後にログインする人に興味がなければ。この場合、必要なものは次のとおりです。

awk -F: '
    $2 == "failed" {fail[$1]++} 
    $2 == "success" {
        if (fail[$1] == 2) print $1
        fail[$1] = 0
    }
' login.log

関連情報