쉘 스크립트를 작성 중인데 고유한 값의 결과와 해당 개수를 한 번에 하나의 파일로 병합하고 싶습니다. 예를 들어, 아래 두 파일에서 데이터를 읽는 경우(첫 번째 열의 숫자는 고유한 개수입니다):
첫 번째 루프는 데이터를 읽습니다.
3 Dog
1 Cat
5 Horse
두 번째 루프에서 데이터 읽기
1 Dog
3 Cat
1 Horse
2 Goat
내 "카운트 파일"을 다음과 같이 덮어쓰도록 두 번째 파일과 첫 번째 파일을 병합하고 싶습니다.
두 번째 루프가 완료된 후의 결과 파일
4 Dog
4 Cat
6 Horse
2 Goat
데이터 세트가 크고 파일을 다운로드하는 것보다 파일을 읽고 삭제하는 것이 더 낫기 때문에 이 작업을 수행하려고 합니다(또는 파일이 상당히 길기 때문에 cat
파일을 함께 모아서 마지막에 찾는 것). uniq -c
이를 수행할 수 있는 방법이 있습니까? 감사합니다!
답변1
이 방법은 awk
임시 파일 tallytmp
과 이름이 지정된 단순 실행 횟수를 합산하는 데 사용됩니다 tally
. sort
두 번째 필드( -k2
) 에 두 개의 카운트 파일을 함께 넣었습니다 .
tally
시작하려면 빈 파일이 필요하므로 touch tally
각 반복마다 다음이 수행됩니다.
uniq -c file > tallytmp
sort -k2 tally tallytmp \
|awk '{
if($2==prev){
tot+=$1
}else{
print tot,prev;
tot=$1;pc=$1;prev=$2
}
}END{
print tot,prev
}' > tallyresult
cp tallyresult tally
(계속해서 awk
스크립트를 한 줄에 넣으십시오.)
sort|awk
논리적으로 파이프를 직접 리디렉션할 수 있어야 tally
하지만 sort
여전히 사용하므로 tallyresult
결과 파일에 복사하기 전에 두 번째 임시 파일이 필요합니다 tally
.
제공된 두 반복의 출력은 실제로 다음과 같습니다.
[blank line]
4 Cat
4 Dog
2 Goat
6 Horse
2번 필드의 순서를 기준으로 순서가 뒤섞여 있는데 잘 동작합니다. 나는 그것을 사용하여 몇 가지 반복을 실행할 수 있었습니다.
답변2
누군가 내 이전 답변에 찬성 투표를 했기 때문에 당연히 새로운 솔루션을 고안해야 했습니다! 이것은 두 가지 이유로 더 좋습니다:
- 순수하고
bash
해시 테이블을 사용합니다.awk
- 정크 빈 줄이 표시되지 않습니다.
- 원하는 만큼의 파일을 추가할 수 있습니다
tally
(3가지 이유). - 파일이
tally
비어 있을 수 있습니다(4가지 이유). - 임시 파일이 필요하지 않습니다("그건 생각하지 못했어요" 등).
다음을 다른 이름으로 저장하세요.tally.sh
#!/bin/bash
# define the associative array tally_table
declare -A tally_table
while read line ; do
k=($line)
[ -n "${k[1]}" ] && (( tot[${k[1]}] += ${k[0]} ))
done <<HERE
$(cat tally $@)
HERE
for i in "${!tally[@]}"; do
echo "${tally[$i]} $i"
done > tally
cat tally
다음 줄로 tally
이름이 지정된 새 보고서 파일을 삭제하고 생성해 보십시오 .file
1 Horse
3 Monkey
그런 다음 입력하세요.
$ ./tally.sh file
3 Monkey
1 Horse
이제 newfile
몇 줄의 이름으로 다른 보고서를 만듭니다.
5 Horse
2 Pig
그리고 먹이를 주세요:
$ ./tally.sh newfile
3 Monkey
6 Horse
2 Pig
항목 Horse
이 올바르게 증가됩니다. 물론 이전과 마찬가지로 순서가 일치하지 않습니다. (어떻게 정렬할지는 모르겠지만개, 고양이, 말, 염소 주문 가능, 또는 Monkey
그 안의 위치. )