Redis 덤프 파일을 읽기 위해 쉘을 사용하고 있습니다.
덤프 파일에는 아래와 같이 3개의 주요 열이 있습니다.
Text:tags:name 682651 520
Text:tags:age 78262 450
Value:cache 77272 672
Value:cache:name 76258 872
New:specific 77628 762
New:test 76628 8622
예상 출력:
Key Count Sum
Text:* 2 970
Value:* 2 1544
New:* 2 9384
문자열(키)로 시작/중간/끝날 수 있는 하위 문자열을 기반으로 열을 확인할 수 있으므로 위의 기대치를 얻고 싶습니다.
답변1
다음 awk
프로그램이 이 작업을 수행합니다.
awk '{split($1,f,/:/);count[f[1]]++;sum[f[1]]+=$3}
END{printf "Key\tCount\tSum\n"; for (k in count) {printf "%s:*\t%d\t%d\n",k,count[k],sum[k]}}' dump.txt
- 이는 먼저 열 1 키를
:
구성 요소로 분할한 다음 이를 배열에 저장합니다f
. 첫 번째 항목(f[1]
)은 모든 추가 처리를 위한 관련 키로 간주됩니다. - 발생 횟수는
count
키를f[1]
배열 인덱스로 사용하여 연관 배열에 저장됩니다. 키를 찾을 때마다 1씩 증가합니다. - 3열의 값의 합은 유사 배열에 저장됩니다
sum
. - 마지막으로 프로그램은 헤더 행을 인쇄한 다음 배열에서 발견된 모든 배열 인덱스를 반복하여
count
배열 인덱스(= 키), 발생 횟수 및 합산된 값을 인쇄합니다.
키가 인쇄되는 순서는 awk
저장된 배열의 내부 논리에 의해 정의됩니다. GNU Awk가 있는 경우 섹션의 속성을 설정하여 순회 순서를 정의할 수 있습니다 PROCINFO["sorted_in"]
. BEGIN
예를 들어
BEGIN{PROCINFO["sorted_in"]="@ind_str_asc"}
awk
"키"를 기준으로 항목이 사전순으로 오름차순으로 인쇄 됩니다 .
답변2
첫 번째 필드 이후의 모든 내용이 다음 :
으로 대체 되도록 첫 번째 필드를 수정하는 것부터 시작하세요 *
.
awk -v OFS='\t' '{ sub(":.*", ":*", $1) }; 1' file
이 명령은 확장 정규 표현식의 첫 번째 항목을 리터럴 문자열로 대체하여 awk
공백으로 구분된 첫 번째 필드를 수정합니다 . 데이터에 따라 탭으로 구분된 다음 데이터가 출력됩니다.:.*
:*
Text:* 682651 520
Text:* 78262 450
Value:* 77272 672
Value:* 76258 872
New:* 77628 762
New:* 76628 8622
그런 다음 각 그룹의 축소된 행 수를 계산하고 세 번째 필드를 합산하면서 탭으로 구분된 첫 번째 필드로 그룹화할 수 있습니다. 한 가지 방법은 GNU를 사용하는 것입니다 datamash
.
awk -v OFS='\t' '{ sub(":.*", ":*", $1) }; 1' file |
datamash groupby 1 count 1 sum 3
awk
원래 입력이 정렬되지 않은 경우 데이터가 전달되거나 sort
해당 datamash
옵션 -s
이 사용됩니다.
그러면 다음이 출력됩니다(탭으로 구분됨).
Text:* 2 970
Value:* 2 1544
New:* 2 9384
헤더를 출력하려면 먼저 다음을 호출하세요.
printf '%s\t%s\t%s\n' 'Key' 'Count' 'Sum'
완전한 것은 file
몇 가지 새로운 파일을 읽고 쓰는 것입니다 output
.
{
printf '%s\t%s\t%s\n' 'Key' 'Count' 'Sum'
awk -v OFS='\t' '{ sub(":.*", ":*", $1) }; 1' |
datamash groupby 1 count 1 sum 3
} <file >output
답변3
$ awk -F'[:[:space:]]+' '
{ cnt[$1]++; sum[$1]+=$NF }
END {
print "Key", "Count", "Sum"
for (key in cnt) {
print key":*", cnt[key], sum[key]
}
}
' file | column -t
Key Count Sum
Value:* 2 1544
Text:* 2 970
New:* 2 9384
답변4
사용행복하다(이전 Perl_6)
~$ raku -e 'my (@k, @v); given lines.map(*.words).list { \
@k = .map(*.[0].split(":").[0]); @v = .map(*.[2]) }; \
my %count1 = Bag(@k); my %agg1.=append: [Z=>] @k, @v; \
my %sum1; for %agg1 { %sum1.append: $_.key => [+] $_.value }; \
for ([Z] %count1.sort, %sum1.sort) { \
say .[0].key ~qb[\t]~ .[0].value ~qb[\t]~ .[1].value};' file
입력 예:
Text:tags:name 682651 520
Text:tags:age 78262 450
Value:cache 77272 672
Value:cache:name 76258 872
New:specific 77628 762
New:test 76628 8622
예제 출력:
New 2 9384
Text 2 970
Value 2 1544
이 솔루션은 모든 Perl 계열 언어에 존재하는 해싱 기능을 활용하며 특별히 Raku로 작성되었습니다.
즉, lines
를 읽고 각 줄은 공백으로 구분된 줄로 분할됩니다 words
( map
이것은 Raku가 "모든" 줄 요소 내에서 작업하도록 지시하는 것입니다). 데이터는 @k
콜론 다음의 첫 번째 문자열 요소를 포함하는 배열과 세 번째 열만 포함하는 배열(0 인덱스 = 2)에 저장됩니다. 이 시점에서 배열은 다음과 같습니다.split
@v
#Add this statement:
.say for @k, @v;
#Returns:
[Text Text Value Value New New]
[520 450 672 872 762 8622]
Raku에는 Bag()
각 키의 발생 횟수(개수)를 제공하는 기능이 내장되어 있습니다(행 사용 my %count1 = Bag(@k);
).
이로부터 및 열을 "압축"하여 함께 쌍을 이루고 해시에 넣는 %agg1
집계 해시가 생성됩니다 . 물론 해시의 한 가지 속성은 각 해시가 고유하다는 것입니다. 따라서 동일한 해시와 관련된 배열 요소는 각 키를 구성하는 배열 요소에 배치됩니다 . 이 시점에서 해시는 다음과 같습니다.@k
@v
=>
append
%agg1
key
values
key
value
%agg1
#Add this statement:
.say for %agg1.sort;
#Returns:
New => [762 8622]
Text => [520 450]
Value => [672 872]
%agg1
%sum1
그런 다음 해당 해시는 다시 반복되어 개인을 합리적인 방식으로 합산하는 해시를 생성합니다. 마지막으로 데이터는 탭으로 구분되어 출력되며(따옴표로 묶은 탭은 코드에서 큰따옴표의 필요성을 줄임) 물결표를 통해 문자열 연결이 수행됩니다.values
key
~qb[\t]~
\t
~
https://andrewshitov.com/2020/03/16/a- Couple-of-syntax-sweets-in-raku/
https://youtu.be/wViVLytlwb8
https://raku.org