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