SQL 쿼리에서 내보낸 데이터를 파일에 넣었습니다 temp.log
.
아래는 샘플 데이터입니다. 머리글 행 뒤의 항목은 첫 번째 열을 기준으로 정렬됩니다.
또한 노드(36,54,69,76)를 고정 목록으로 간주합니다.
<Name> <Status> <Node> <Requests>
AString1 Success 36 1
AString1 Success 54 4
AString1 Success 69 3
AString1 Success 76 4
BString2 Success 36 1
BString2 Success 54 2
BString2 Success 69 3
BString2 Success 76 1
CString3 Success 36 8
CString3 Success 54 7
CString3 Success 76 8
DString4 Success 36 8
DString4 Success 54 4
DString4 Success 69 12
DString4 Success 76 7
다음 출력이 필요합니다
<Name> <Nodes> <Count of Requests>
Astring1 36 54 69 76 12
BString2 36 54 69 76 7
CString3 36 54 NA 76 23
DString4 36 54 69 76 31
여기의 마지막 열( <Count of Requests>
)은 해당 이름의 각 노드에 대한 총 요청 수를 나타냅니다.
NA
노드가 요청을 받지 못한 경우 이 내용이 인쇄되어야 합니다. (o/p에서 CString3 줄을 볼 수 있습니다. 노드 값 행이 누락되었습니다 . 이 경우 다음과 같이 69
되어야 합니다 .NA
CString3 36 54 NA 76 23
성공 사례에서 DString4 -DString4 36 54 69 76 31
awk 명령을 사용하여 이를 수행할 수 있습니까?
답변1
$ cat tst.awk
NR==1 {
print "<Name>", "<Nodes>", "<Count of Requests>"
next
}
$1 != prev {
if ( NR > 2 ) {
prt()
}
prev = $1
}
{
reqs[$3]
numReqs += $4
}
END { prt() }
function prt( i, n, node, nodes) {
n = split("36 54 69 76", nodes)
printf "%s ", prev
for (i=1; i<=n; i++) {
node = nodes[i]
printf "%s ", (node in reqs ? node : "NA")
}
print numReqs
delete reqs
numReqs = 0
}
$ awk -f tst.awk file
<Name> <Nodes> <Count of Requests>
AString1 36 54 69 76 12
BString2 36 54 69 76 7
CString3 36 54 NA 76 23
DString4 36 54 69 76 31
답변2
또 다른 awk 솔루션은 다음과 같습니다.
$ awk '{if(NR==1){printf "%s\t%s\t%s\n", "<Name>","<Nodes>","<Count of Requests>"} else{nodes[$3]=1; a[$1][$3]++; sum[$1]+=$4}}END{for(string in a){ printf "%s\t", string; for(i in nodes){ (a[string][i]) ? val=i : val="NA"; printf "%s ",val }; printf "\t%d\n",sum[string];}}' file
<Name> <Nodes> <Count of Requests>
CString3 36 54 NA 76 23
DString4 36 54 69 76 31
AString1 36 54 69 76 12
BString2 36 54 69 76 7
나중에 쉽게 구분할 수 있도록 각 항목("이름", "노드" 및 "요청 개수") 사이에 탭 문자를 추가했습니다.
다음은 더 깔끔한 형식의 동일한 스크립트입니다(여전히 터미널에 직접 복사/붙여넣기 가능).
awk '{
## If this is the first line
if(NR==1){
## Set up the nodes array with the desired values
nodes[36]=1;
nodes[54]=1;
nodes[69]=1;
nodes[76]=1;
## Print the header
printf "%s\t%s\t%s\n", "<Name>","<Nodes>","<Count of Requests>"
}
## For all except the first line
else{
## Save this node in the nodes array
nodes[$3]=1;
## add this node to the values found for this string
a[$1][$3]++;
## add the number of requests
sum[$1]+=$4
}
}
## After we have finished reading the file
END{
## a holds all the first fields, the various strings
for(string in a){
## Print the current string and a tab
printf "%s\t", string;
## For each target node
for(i in nodes){
## If this node has a value for this string, use the value.
## If it does not, use "NA".
(a[string][i]) ? val=i : val="NA";
## Print the value for the node
printf "%s ",val
};
## Print the sum
printf "\t%d\n",sum[string];
}
}' file
답변3
두 개의 인덱스 배열을 사용하여 각 이름에 대한 요청 수와 기존 노드를 저장할 수 있으며, 인쇄하기 전에 기존 노드 배열을 고정 노드 배열과 비교할 수 있습니다. 예:
awk 'BEGIN {
totalNodes="36 54 69 76"
}
NR==1 {print "<Name> <Nodes> <Count of Requests>"};
NR>1 {
count[$1]+=$4; nodesTmp[$1]=nodesTmp[$1]" "$3;
}
END{
for (i in count) {
if(totalNodes!=nodesTmp[i]) {
split(totalNodes,tmp);
for(j in tmp){
if(nodesTmp[i]!~tmp[j]){
nodes[i]=nodes[i]" NA"
}
else {
nodes[i]=nodes[i]" "tmp[j]
}
}
}
else{
nodes[i]=nodesTmp[i]
};
print i, nodes[i], count[i] | "sort"
};
}' temp.log
답변4
GNU와 실제 이중 인덱스 배열을 가정하면 awk
다음 PROCINFO
이 작동합니다.
gawk 'BEGIN{PROCINFO["sorted_in"]="@ind_str_asc"}
FNR>1{nodes[$3]=1; total[$1]+=$4; sgl_nodes[$1][$3]=1}
END{
printf "<Name> <Nodes> <Count of Requests>\n"
for (f in sgl_nodes) {
printf "%s%s",f,OFS;
PROCINFO["sorted_in"]="@ind_num_asc";
for (g in nodes) {
if (sgl_nodes[f][g]) printf "%s%s",g,OFS; else printf "NA%s",OFS
};
PROCINFO["sorted_in"]="@ind_str_asc";
printf "%d%s",total[f],ORS
}
}' temp.log
nodes
이는 실제로 발생한 노드 번호 와 2D 배열의 각 이름과 연관된 노드 번호를 배열에 등록하며 sgl_nodes
첫 번째 인덱스 값과 함께 저장됩니다. 처리하는 동안 <Name>
해당 값에 해당하는 배열 인덱스 아래 배열의 총 요청 수도 합산됩니다.total
<Name>
파일 끝에서 먼저 헤더 라인을 인쇄한 다음 배열을 반복하여 sgl_nodes
각 값의 이름 <Name>
( 의 첫 번째 인덱스 sgl_nodes
)을 인쇄한 다음 등록된 모든 노드를 반복하여 nodes
노드 번호(특정 에 대해 발견된 경우 <Name>
) 를 인쇄합니다. 또는 NA
(해당 노드가 손실된 경우) 마지막으로 총 요청 수입니다.
<Name>
PROCINFO
해당 섹션에서 수행된 설정 덕분에 값을 오름차순으로 인쇄합니다. BEGIN
이 설정은 배열을 반복하기 위해 숫자 정렬로 재정의됩니다 nodes
.
temp.log
이 방법은 정렬되는 항목 에 의존하지 않으며 자동으로 노드 번호를 인식합니다.
노드 번호 중 하나가 누락되면 자동 노드 번호 인식의 이점이 문제가 됩니다.모두기입. 그러나 노드 목록이 고정된 것으로 간주될 수 있다고 말씀하셨기 때문에 목록을 하드코딩하면 이 문제를 피할 수 있습니다.
gawk 'BEGIN{PROCINFO["sorted_in"]="@ind_str_asc";split("36 54 69 76",nodes)}
FNR>1{total[$1]+=$4; sgl_nodes[$1][$3]=1}
END{
printf "<Name> <Nodes> <Count of Requests>\n"
for (f in sgl_nodes) {
printf "%s%s",f,OFS;
for (g=1;g<=4;g++) {
if (sgl_nodes[f][nodes[g]]) printf "%s%s",nodes[g],OFS; else printf "NA%s",OFS
};
printf "%d%s",total[f],ORS
}
}' temp.log