두 개의 조건이 있는 두 개의 열로 Uniq

두 개의 조건이 있는 두 개의 열로 Uniq

열이 있는 테이블이 있어요. 첫 번째 열에는 사용자가 로그인한 시간이 있고, 두 번째 열에는 사용자 이름이 있습니다.

13:15:39  fxs1cia1qulm1lk  
13:15:39  fxs1cia1qulm1lk  
13:15:39  fxs1cia1qulm1lk  
13:15:42  faaaa2aa11111  
13:15:49  terd1sfsd11fsdf  
13:15:49  terd1sfsd11fsdf  
13:15:49  terd1sfsd11fsdf  
13:15:59  21erdsf123sdfsdf   
13:15:59  21erdsf123sdfsdf   
13:15:59  21erdsf123sdfsdf   
13:15:59  21erdsf123sdfsdf   
13:17:50  abcasbbabadab  
13:17:50  abcasbbabadab  
13:17:50  abcasbbabadab  
13:17:50  abcasbbabadab   
13:19:19  fxs1ce1iulmla   
13:19:19  fxs1ce1iulmla  
13:19:19  fxs1ce1iulmla   
13:20:42  faaa2a0a1111

그래서 내가 무엇을 해야 합니까? 이 두 열을 사용하여 고유한 업데이트를 수행해야 합니다. 그리고 사용자 로깅 시간과 사용자 이름이 동일하면 해당 사용자가 3번 이상 로그인했다고 해야 합니다. 나는 짧은 스크립트를 작성했습니다:

log_file=/root/log
temp_file=/root/temp
temp_file2=/root/temp2

cat /dev/null > $temp_file
cat /dev/null > $temp_file2
cat /dev/null > $result_file

cat $log_file | awk '{print $1}' | tail -n 20 > $temp_file
cat $log_file | awk '{print $5}' | tail -n 20 > $temp_file2

for i in `uniq -c $temp_file | awk '{print $1}'`; do
for y in `uniq -c $temp_file2 | awk '{print $2}'`; do
if [ $i -gt 3 ] && [ $y -gt 3 ]; then
s=`uniq -c $temp_file2 | awk '$1 == '$i`
echo "The user $s has logged more than 3 times"
fi
done
done

이 스크립트가 맞는지 확인해 보세요. 왜냐하면 echo로 스크립트를 출력한 후 다음과 같은 결과가 나왔기 때문입니다.

The user       4 21erdsf123sdfsdf   
      4 abcasbbabadab  has logged more than 3 times
The user       4 21erdsf123sdfsdf   
      4 abcasbbabadab  has logged more than 3 times
The user       4 21erdsf123sdfsdf   
      4 abcasbbabadab  has logged more than 3 times
The user       4 21erdsf123sdfsdf   
      4 abcasbbabadab  has logged more than 3 times

하지만 나는 다음과 같은 출력을 원합니다.

The user       4 21erdsf123sdfsdf has logged more than 3 times
The user       4 abcasbbabadab  has logged more than 3 times

그리고 그게 다야. 내가 실수한 부분이 있나요? 도와주세요.

답변1

다음을 사용하면 매우 간단한 방법으로 이 작업을 수행할 수 있습니다.awk

awk '{ users[$2]++ }
END {
     for (user in users)
       if (users[user] > 1)
         printf "%s logged in %d times\n", user, users[user]
    }' < /root.log

이 프로그램은 모든 사용자 수를 포함하는 연관 배열(해시라고도 함)을 생성하는 root.log를 스캔한 다음 1보다 큰 사용자를 인쇄합니다.

답변2

그렇다면 유일한 문제는 동일한 출력을 여러 번 인쇄한다는 것입니다. 왜 uniq를 통해 파이프하면 안 되나요? 다른 임시 파일로 덤프한 다음 uniq를 실행하시겠습니까?

그것이 당신이 묻는 것이 아니라면 몇 가지 관찰 사항이 있습니다.

  • Bash/sh에서 줄로 구분된 데이터를 작업하는 것은 일반적으로 가치 있는 것보다 더 문제가 많습니다. 해결책이 분명하지 않다면 항상 IFS를 다룰 필요가 없는 스크립팅 언어를 찾으십시오. (IFS var가 무엇인지 모른다면 줄로 구분된 데이터에 대해 bash/sh를 사용하지 않는 것이 좋습니다.)
  • 당신은 이미 awk를 사용하고 있으므로 모든 것을 awk 스크립트로 수행할 수 있을 것입니다.
  • 관심 있는 라인은 동일하므로 하시면 됩니다 sort logfile | uniq -c.
  • uniq 이전에 파일을 정렬하지 않으므로 동일한 줄이 서로 옆에 있지 않으면 uniq가 작동하지 않습니다. 예를 들어 bob과 joe가 동시에 로그인하고 두 로그 항목이 번갈아 나타나는 경우입니다.
  • 항상 grep -c가 있습니다
  • sort 명령, 특히 -d, -n, -k 및 -t를 읽어보세요.

업데이트

쉘 스크립팅에 대한 조언을 구하고 있습니까? 아니면 현재 3개 이상의 세션에 로그인한 사람을 어떻게 알 수 있는지에 대한 실용적인 답변을 찾고 있습니까?

스크립팅 조언:

  • 개행 문자를 포함한 $s전체 문자열이 포함되어 있다고 확신합니다 . 4 21erdsf123sdfsdf <newline> 4 abcasbbabadab이유를 잘 모르겠습니다.
  • 왜 그러는가 awk '{print $5}'? 귀하의 예제 데이터를 복사하여 실행해 보았지만 awk '{print $5}'많은 줄 바꿈 외에는 아무것도 얻지 못했습니다.
  • 의 내용을 살펴보고 $temp_file예상 $temp_file2한 내용인지 확인하셨나요?
  • 이는 tail -n 20'최근' 항목만 원하고 얼마나 최근 항목인지는 상관하지 않는다는 의미입니다. 이것이 사실입니까?
  • cat /dev/null > $file이 중복되니까 그냥 빼내세요.
  • cat $logfile다음으로 교체sort $logfile
  • 루프 들여쓰기

기본적으로 이 스크립트는 여러분이 원하는 대로 작동하지 않으며, 여러분이 어떻게 작동하도록 의도했는지 알 수 없으므로 더 구체적인 조언을 드릴 수 없습니다. 죄송합니다.

현실적인

  • @greg-tarsa의 awk 스크립트를 사용하세요('e에게 사과드립니다, Greg me heartie, 저는 '사용자'를 연결하지 않았는지 알지 못합니다''에 'is 이름'의 공백이 있습니다)
  • 유닉스 박스에 대한 현재 로그인에 대해 이야기하고 있습니까? 명령 을 시도해 보셨나요 who? EG who | awk '{ print $1}' | sort | uniq -c | sort -d -r또는 last명령?
  • 이미 구현하려는 솔루션을 차단하는 보다 구체적인 질문(두 조건이 있는 두 열의 Uniq) 대신 전반적인 질문(누가 너무 많이 로그인했는지 어떻게 알 수 있습니까?)에 대한 답변을 검색하십시오. . 쉘 스크립팅을 연습하는 데 더 관심이 있다면 그렇게 말하는 방식으로 질문하십시오.

관련 정보