동일한 디렉토리에 있는 다른 파일과 파일을 비교하고 싶습니다.
file1.txt
포함하다:
move 34#123#
get 11#278
put 33#29#567#23
file1.txt
파일 1.txt
과 2.txt
.
1.txt
포함하다:
move 11
put 34
run 13
2.txt
포함하다:
get 14
move 66
나에게 필요한 결과는 다음과 같습니다.
move 2
get 1
put 1
어떻게 해야 하나요?
답변1
해결책 은 다음과 같습니다 awk
.
$ awk 'FNR==NR{a[$1];next}($1 in a){++a[$1]}
END{for(i in a){print i" "a[i]}}' file1.txt 1.txt 2.txt
put 1
get 1
move 2
설명하다
FNR==NR{a[$1];next}
file1.txt
: 처리하는 동안 연관 배열에 발생 항목을 표시합니다 .$1
a
($1 in a){++a[$1]}
: sum을 처리할 때1.txt
연관 배열에 존재하는지2.txt
확인하고 , 존재한다면 개수에 1을 더한다.$1
a
- 마지막으로 연관 배열을 반복하여
a
키(파일의 첫 번째 필드)와 해당 값(1.txt
합계에서 발생 횟수2.txt
)을 인쇄합니다.
perl
동일한 논리를 사용하는 의 또 다른 솔루션은 다음과 같습니다 .
$ perl -alne '++$i;
if ($. == $i) {
$h{$F[0]}=0;
close ARGV if eof;
next;
}
++$h{$F[0]} if defined $h{$F[0]};
END {
for (keys %h) {
print $_." ".$h{$_};
}
}' file1.txt 1.txt 2.txt
move 2
get 1
put 1
답변2
grep
, awk
, sort
, & 등 다양한 도구를 사용하여 대안을 표시합니다 uniq
. 물론 더 많은 도구를 사용하지만 AWK보다 무슨 일이 일어나고 있는지 이해하는 것이 더 쉽다는 것을 알았습니다.
$ for i in 1.txt 2.txt; do grep -f <(awk '{print $1}' $i) file1.txt; done | \
awk '{print $1}' | sort | uniq -c
예
$ for i in 1.txt 2.txt; do grep -f <(awk '{print $1}' $i) file1.txt; done | \
awk '{print $1}' | sort | uniq -c
1 get
2 move
1 put
어떻게 작동하나요?
다음은 약간 확장된 예입니다.
$ for i in 1.txt 2.txt; do
grep -f <(awk '{print $1}' $i) file1.txt
done | \
awk '{print $1}' | sort | uniq -c
이 for
루프는 일치시키려는 2개의 파일을 반복합니다 1.txt
. 반복할 때마다 대상 파일에서 2.txt
파일 중 하나의 첫 번째 열을 정적 문자열 세트로 사용합니다 .grep
file1.txt
$ grep -f <(awk '{print $1}' $i) file1.txt
루프의 각 파일에 대해 명령을 실행한 후 for
모든 출력을 가져오고 그 안에 있는 첫 번째 열만 선택합니다.
move
put
move
get
그런 다음 sort
sum을 사용하여 우리 uniq
가 보는 각 유형의 수를 계산합니다.
답변3
또 다른 접근 방식은 다음과 같습니다 join
.
join -1 1 -2 2 -o 0 2.1 <(sort -k1,1 file1.txt) <(cut -d ' ' -f1 1.txt 2.txt | sort | uniq -c)
출력은 다음과 같이 정렬됩니다.
get 1
move 2
put 1
file1.txt
예를 들어 주문을 유지하려는 경우
move 2
get 1
put 1
다음을 실행할 수 있습니다.
join -j2 -o 1.1 0 2.1 <(nl -ba -nrz file1.txt | sort -k2,2) \
<(cut -d ' ' -f1 1.txt 2.txt | sort | uniq -c) | sort -k1 | cut -d ' ' -f2-