중복 목록을 제거하되 해당 부분을 그룹화하세요.

중복 목록을 제거하되 해당 부분을 그룹화하세요.

실패한 로그인에 대한 일부 액세스 규칙을 컴파일하고 있으며 일부 파이핑 후에 다음과 같은 결과를 얻었습니다.

cat <<INPUT | sort -k 3,3 --unique
Deny from 13.42.98.142 # demo
Deny from 13.42.98.142 # test
Deny from 13.42.98.142 # user
Deny from 133.142.200.152 # admin
INPUT

단지 관심을 끌기 위해 시도한 로그인(마지막 필드)을 유지하고 싶습니다. 내 테스트 코드는 다음과 같이 출력됩니다.

Deny from 13.42.98.142 # demo
Deny from 133.142.200.152 # admin

다음과 유사한 출력을 찾고 있습니다.

Deny from 13.42.98.142 # demo, test, user
Deny from 133.142.200.152 # admin

또는 더 나은 방법은 다음과 같습니다(유효한 구문이므로 .htaccess).

# demo, test, user
Deny from 13.42.98.142
# admin
Deny from 133.142.200.152

노트: 제가 입력한 내용은 지금 제가 만드는 방법입니다. 저는 완고하지 않고 우아한 솔루션에 더 잘 어울리면 변경할 수 있습니다. 또한 쉘에서 목록 그룹화를 구현하는 방법에 대한 일반적인 답변도 수락하겠습니다.

답변1

이것은 작업입니다 awk.

awk -F'#' '
    { a[$1] = (a[$1] ? a[$1] "," $2 : $2) }
    END { for(x in a) print "#" a[x] ORS x }
' file

# admin
Deny from 133.142.200.152 
# demo, test, user
Deny from 13.42.98.142 

print여러 출력 형식을 얻으려면 마지막 문을 수정하십시오 . 레코드의 순서는 어떤 키로도 정렬되지 않으므로 귀하의 목적에 필요하지 않을 것 같습니다.

GNU awk를 사용하여 키별로(문자열, 오름차순) 정렬해야 하는 경우 다음을 추가할 수 있습니다.

PROCINFO["sorted_in"] = "@ind_str_asc"

루핑하기 전에 for. 인용하다:GNU awk 배열 정렬

답변2

GNU를 사용하여 datamash첫 번째 #구분 기호 필드로 그룹화하고 두 번째 필드를 축소합니다.

datamash -s -t '#' groupby 1 collapse 2 <<'END_RULES'
Deny from 13.42.98.142 # demo
Deny from 13.42.98.142 # test
Deny from 13.42.98.142 # user
Deny from 133.142.200.152 # admin
END_RULES

-s옵션은 입력 데이터를 정렬하는데, 이 경우 정렬된 것처럼 보이기 때문에 꼭 필요한 것은 아닙니다.

산출:

Deny from 13.42.98.142 # demo, test, user
Deny from 133.142.200.152 # admin

답변3

어떤 awk.

awk -v sep=', ' '
    { usr=$NF; sub(/[[:blank:]]*#.*$/, "");
      if(!seen[$0]++) ordr[$0]=++c;
      usrsRec[ordr[$0], $0]=dataRec[$0]= ($0 in dataRec?dataRec[$0] sep:"") usr
    }
END { for(recNr=1; recNr<=c; recNr++)
          for(data in dataRec)
              if((recNr, data) in usrsRec)
                  print "#", usrsRec[recNr, data] ORS data
 }' infile

산출:

# demo, test, user
Deny from 13.42.98.142
# admin
Deny from 133.142.200.152 

관련 정보