ファイルの日付に基づいて最新のアイテムをインポートする

ファイルの日付に基づいて最新のアイテムをインポートする

以下でお手伝いできることを確認してください。いくつかの他の方法を試しましたが、欲しいものを手に入れることはできません。

ユーザーID.txt

user1
user2
user3
user4
user5

ファイル1.txt

AmLogin server1 [03/Feb/2021:00:04:09 -0600] "11.11.11.11 uid=user1,ou=users,ou=company1,o=company"
AmLogin server1 [03/Feb/2021:00:05:11 -0600] "22.22.22.22 uid=user2,ou=users,ou=company1,o=company"
AmLogin server1 [03/Feb/2021:00:08:25 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company"

ファイル2.txt

AmLogin server2 [04/Feb/2021:00:01:09 -0600] "11.11.11.11 uid=user1,ou=users,ou=company1,o=company"
AmLogin server2 [04/Feb/2021:00:01:11 -0600] "22.22.22.22 uid=user2,ou=users,ou=company1,o=company"
AmLogin server2 [04/Feb/2021:00:01:25 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company"
AmLogin server2 [04/Feb/2021:00:02:30 -0600] "11.11.11.11 uid=user1,ou=users,ou=company1,o=company"
AmLogin server2 [04/Feb/2021:00:05:20 -0600] "2.2.2.2 uid=user2,ou=people,dc=company2,dc=com"
AmLogin server5 [07/Feb/2021:00:02:30 -0600] "11.11.11.11 uid=user4,ou=People,ou=company1,o=company"
AmLogin server5 [08/Feb/2021:00:05:20 -0600] "2.2.2.2 uid=user5,ou=people,ou=employees,dc=company2,dc=com"

ファイル3.txt

AmLogin server3 [05/Feb/2021:00:01:11 -0600] "22.22.22.22 uid=user2,ou=users,ou=company1,o=company"
AmLogin server3 [05/Feb/2021:00:01:25 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company"
AmLogin server3 [05/Feb/2021:00:09:25 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company"
AmLogin server3 [08/Dec/2020:00:11:44 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company" "App1" [0002222000] [0] []
AmLogin server3 [09/Feb/2021:00:07:50 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company" "App2" [0003455000] [0] []

次の詳細を使用して、すべてのユーザーの最新のログイン情報を取得したいと思います。上記の内容はサンプルファイルのみです。データを抽出する必要がある100の巨大なログファイルがあります。以下では、user2は2回言及され、ユーザーIDは同じように見えますが、異なる識別名(DN)を持つ2人の異なるユーザーです。識別名は、ユーザーのフルパスを表します。 user2 の例は次のとおりです。ou =ユーザー、ou =会社1、o =会社他のuser2が次に存在します。ou=人、dc=会社2、dc=com。以下のuser4の場合ou=従業員、ou=会社1、o=会社user5 の場合、次の場所にあります。ou=従業員、ou=従業員、dc=company2,dc=com

二重引用符の後の末尾(user3)の一部のエントリには、無視できる任意のテキスト(「App1」[0002222000] [0] [])が含まれています。

期待される出力.txt

user1|04/Feb/2021:00:02:30|uid=user1,ou=users,ou=company1,o=company
user2|05/Feb/2021:00:01:11|uid=user2,ou=users,ou=company1,o=company
user2|04/Feb/2021:00:05:20|uid=user2,ou=people,dc=company2,dc=com
user3|09/Feb/2021:00:07:50 -0600|uid=user3,ou=users,ou=company1,o=company
user4|07/Feb/2021:00:02:30|uid=user4,ou=People,ou=company1,o=company
user5|08/Feb/2021:00:05:20|uid=user5,ou=people,ou=employees,dc=company2,dc=com

それとも時間がなければ簡単になります。

期待される出力.txt

user1|04/Feb/2021|uid=user1,ou=users,ou=company1,o=company
user2|05/Feb/2021|uid=user2,ou=users,ou=company1,o=company
user2|04/Feb/2021|uid=user2,ou=people,dc=company2,dc=com
user3|09/Feb/2021|uid=user3,ou=users,ou=company1,o=company
user4|07/Feb/2021|uid=user4,ou=People,ou=company1,o=company
user5|08/Feb/2021|uid=user5,ou=people,ou=employees,dc=company2,dc=com

usernamesを使用してすべてのファイルをgrepingしようとしましたが、$i時間がかかります。

grep $i file*.txt | tail -1

答え1

#!/bin/sh

while read -r user
  do
    for group in users people
      do
        sed -nr "s/.*\[(\S+).*\s(uid=$user,ou=$group,.*)./$user|\1|\2/p" file*.txt | sort -t\| -k2.8nr -k2.4Mr -k2.1nr -k2.13,2.20r | grep -m1 "|uid=$user,ou=$group,"
    done
done < userid.txt

編集する:

ログファイルがソートされたら、各DNを繰り返し、tail -n1最初のパスはユーザーを検索し、2番目のパスuserdn.txtの別の入力ファイルを生成します。

#!/bin/sh

# list of users (from logs)
grep -Fiwhf userid.txt file*.txt | grep -io 'uid=[^"]*' | sort --ignore-case -u > userdn.txt

# last login
while read -r user
  do
    grep -Fiwh "$user" file*.txt | tail -n1 | sed -nr 's/.*\[(\S+).*\suid=([^,]+)(.*)./\2|\1|uid=\2\3/p'
done < userdn.txt

またはプロセスの交換を介して(bashのみ)

#!/bin/bash

while read -r user
  do
    grep -Fiwh "$user" file*.txt | tail -n1 | sed -nr 's/.*\[(\S+).*\suid=([^,]+)(.*)./\2|\1|uid=\2\3/p'
done < <(grep -Fiwhf userid.txt file*.txt | grep -io 'uid=[^"]*' | sort --ignore-case -u)

ログファイルがソートされておらず、ディスク容量よりも時間がかかる場合は、手順3に一度だけソートして時間を節約してください。

-create userdn.txt
- ログファイルを日付ごとに大きな単一ファイルにソート - 各DNを
繰り返します。bigfile.txt

#!/bin/sh

# list of users (from logs)
grep -Fiwhf userid.txt file*.txt | grep -io 'uid=[^"]*' | sort --ignore-case -u > userdn.txt

# merge log files
grep -Fiwhf userdn.txt file*.txt | sed -nr 's/.*\[(\S+).*\suid=([^,]+)(.*)./\2|\1|uid=\2\3/p' | sort -t\| -k2.8nr -k2.4Mr -k2.1nr -k2.13,2.20r > bigfile.txt

# last login
while read -r user
  do
    grep -Fiwm1 "$user" bigfile.txt
done < userdn.txt

各ログは各ユーザーに対して複数回処理されるため、これはまだ良い解決策ではありません。他の解決策awkjoin何かがpasteあるはずですuniq

理想的には結合します...

tac file*.txt | grep -m1 -f userdn.txt

...しかし、これは2つの理由で機能しません。
tac期待どおりに動作するのではなく、各ログが順次処理されます。検索せず
-m1に結合-fみんなモード(ファイル内)、それ以降は停止します。どの柄。
ただし、これはすでにソートされたログにのみ適用されます。 :(


必要なのは、ログファイルを単一のパスとして処理して各行を読み取り、結果を別のファイルに書き込むことです。ここで、書き込みイベントは関数を介して実装されます。

この機能は次のことを行う必要があります。

- DNがすでに存在することを確認する
- 日付を比較する
- 既存のアイテムを更新する
- 新しいアイテムのみを追加

#!/bin/bash

shopt -s extglob

# function compare date
compare () {
  [ -n "$2" ] || return 1

  # sort array
  for date in "$@"
    do
      echo "$date"
  done | sort -k1.8n -k1.4M -k1.1n -k1.13,1.20 | tail -n1

  return 0
}

# function write last_login.txt
update () {
  local file=$1 line=$2
  [ -n "$line" ] || return 1

  # string manipulation
  dn=${line#*\"}; dn=${dn%%\"*}; dn=${dn#*+([[:blank:]])}; [ -n "$dn" ] || return 1
  user=${dn%%,*}; user=${user#*=};
  date2=${line#*[}; date2=${date2%%]*}; date2=${date2%+([[:blank:]])*};

  [ -f "$file" ] && date1=$(grep -Fiwm1 "$dn" "$file" | cut -d\| -f2)
  if [ -n "$date1" ]
    then
      # DN already exist
      [ "$date1" = "$date2" ] && return 0
      date=$(compare "$date1" "$date2")
      if [ "$date" != "$date1" ]
        then
          # update existing entry
          sed -i "s;$user|$date1|$dn;$user|$date2|$dn;i" "$file"
      fi
    else
      # add new entries only
      echo "$user|$date2|$dn" >> "$file"
  fi

  return 0
}

# create last_login.txt
for file in file*.txt
  do
    [ -f "$file" ] || continue
    echo "processing $file"
    while read -r line
      do
        update last_login.txt "${line//;/,}"
    done < <(tac "$file")
done

# sort last_login.txt
echo -n "sorting... "
sort -o last_login.txt last_login.txt
echo "finished"

exit 0

関連情報