다른 파일과 비교하여 발생 횟수 계산

다른 파일과 비교하여 발생 횟수 계산

두 개의 파일이 있습니다.

F1.txt:

a:erwer|ee
b:eeeee|eee
c:ewrew|erwe

그리고 F2.txt:

a.T1
a.T2
b.T3
C.T7
c.T4

F2.txt에서 F1.txt를 확인하여 a키워드 b발생 횟수를 확인해야 합니다.c

F1.txt의 예상 출력:

a:erwer|ee:total:2
b:eeeee|eeet:total:1
c:ewrew|erwe:total:2

다른 파일의 o/p를 업데이트합니다.

a:2
b:1
c:2

답변1

파일이 너무 크지 않으면 awk를 사용할 수 있습니다.

awk '
BEGIN{FS=".";OFS=":"}
NR==FNR{a[tolower($0)]=0;next}
{ 
    if(tolower($1) in a){
        a[tolower($1)]++
    }
} 
END{
    for(key in a){
        print key, a[key]
    }
}
' F1.txt F2.txt

대소문자를 구분하는 콘텐츠를 원하면 해당 tolower기능을 제거하세요.


수정된 질문에:

awk '
BEGIN{FS="[:.]";OFS=":"}
NR==FNR{l[tolower($1)]=$0;cpt[tolower($1)]=0;next}
{
    if(tolower($1) in cpt){
        cpt[tolower($1)]++
    }
}
END{
    for(key in cpt){
        print l[key],"total",cpt[key]
    }
}
' F1.txt F2.txt

답변2

먼저 F2.txt파일을 필드 구분 기호로 점이 있는 CSV 파일로 처리합니다. 첫 번째 필드를 소문자로 변환한 다음 첫 번째 필드의 고유 값 수를 계산할 수 있습니다. 사용하여밀러다음 ()에서 mlr고유한 첫 번째 필드 값과 해당 개수는 필요에 따라 구분 기호로 사용하여 출력됩니다.:

$ mlr --csv --ifs . --ofs : -N put '$1 = tolower($1)' then count -g 1 F2.txt
a:2
b:1
c:2

이 결과를 필터링하고 의 콘텐츠와 병합하려면 다음을 F1.txt사용합니다 join.

$ mlr --csv --ifs . --ofs : -N put '$1 = tolower($1)' then count -g 1 F2.txt | join -t : F1.txt -
a:erwer|ee:2
b:eeeee|eee:1
c:ewrew|erwe:2

total:끝의 숫자 앞에 문자열을 삽입 하려면 문자열 을 sed 's/.*:/&total:/'.

$ mlr --csv --ifs . --ofs : -N put '$1 = tolower($1)' then count -g 1 F2.txt | join -t : F1.txt - | sed 's/.*:/&total:/'
a:erwer|ee:total:2
b:eeeee|eee:total:1
c:ewrew|erwe:total:2

사용된 변형 awk:

$ awk -F : 'FNR==NR { split($0,a,"."); count[tolower(a[1])]++; next } $1 in count { printf "%s:total:%s\n", $0, count[$1] }' F2.txt F1.txt
a:erwer|ee:total:2
b:eeeee|eee:total:1
c:ewrew|erwe:total:2

코드 awk:

BEGIN { FS = ":" }

FNR==NR {
    split($0,a,".")
    count[tolower(a[1])]++
    next
}

$1 in count {
    printf "%s:total:%s\n", $0, count[$1]
}

재미삼아: Miller의 Docker 이미지를 사용하여 위의 첫 번째 명령을 실행하는 방법을 보여주세요.

docker run --rm -i jauderho/miller:latest \
    --csv --ifs . --ofs : -N \
    put '$1 = tolower($1)' then count -g 1 <F2.txt

... 심지어...

alias mlr='docker run --rm -i jauderho/miller:latest'

mlr --csv --ifs . --ofs : -N put '$1 = tolower($1)' then count -g 1 <F2.txt

답변3

Perl은 awk나 @terdon과 같은 다양한 도구 파이프라인에서 수행할 수 있지만 여기에 적합합니다(그러나 해당 솔루션의 하위 문자열에 대한 경고에 유의하십시오).

다음은 몇 가지 입력 예입니다.

파일 1

a
b
c
d

파일 2

a.T1
a.T2
b.T3
C.T7
c.T4

그리고 예제를 실행해보세요:

% perl count.pl file1 file2
a:2
b:1
c:2
d:0

이것은 상대적으로 구조화된 Perl 버전입니다. 보다 명시적인 파일 처리 대신 언어의 "마법의 readline" 기능을 사용합니다. 오류 처리 기능은 없지만 런타임 시 자동으로 제공됩니다. "slurp 모드"를 사용하여 키 파일을 읽으므로 크기와 메모리에 대한 경고는 해당 파일에 대한 가치가 있을 수 있지만 찾고 있는 키 파일이 매우 클지는 의심스럽습니다. 모든 것을 메모리로 가져오지 않고 한 줄씩 정확하게 반복하므로 file2임의로 커질 수 있습니다. 정규식 일치를 사용하므로 마지막 "." 앞의 모든 내용은 일치합니다. 그러면 'T'는 의 단일 숫자와 일치할 수 있습니다 file1.

#!perl
use warnings;
use strict;

sub get_keys {
 local $/ = undef;
 return { map { lc $_ => 0 } split /\n/, <> };
}

sub count {
 my $m = shift;
 while (<>) {
  if ( m/(.*)\.T\d/ ) {
   $m->{lc $1}++ if exists $m->{lc $1}
  }
 }
 return $m;
}

sub output {
 my $m = shift;
 for my $k ( sort keys %$m ) {
  printf "%s:%d\n", $k, $m->{$k};
 }
 return;
}

output count get_keys;

이것은 동일한 핵심 논리를 사용하는 Perl에 있는 더 짧고 일회용 버전입니다.

#!perl
use warnings;
use strict;

undef $/;
my %map = map { lc $_ => 0 } split /\n/, <>;

$/ = "\n";
while (<>) {
 if ( m/(.*)\.T\d/ ) {
  $map{lc $1}++ if exists $map{lc $1}
 }
}

for my $k ( sort keys %map ) {
  printf "%s:%d\n", $k, $map{$k};
}

동일한 작업을 수행하지만 읽기가 너무 어렵지 않은 짧은 명령줄 버전을 원할 경우 여기에 적합한 두 번째 버전이 있습니다.

% perl -e '
undef $/;
%m = map { lc $_ => 0 } split /\n/, <>;
$/ = "\n";
while (<>) { if ( /(.*)\.T\d/ ) { $m{lc $1}++ } }
for $k ( sort keys %m ) { printf "%s:%d\n", $k, $m{$k}; }
' file1 file2
a:2
b:1
c:2
d:0

또는 BEGIN 및 END 블록과 함께 awk와 같은 입력 자동 루프를 사용하십시오.

% perl -ne '
BEGIN {
 undef $/;
 %m = map { lc $_ => 0 } split /\n/, <>;
 $/ = "\n";
}
if ( /(.*)\.T\d/ ) { $m{lc $1}++ }
END {
 for $k ( sort keys %m ) { printf "%s:%d\n", $k, $m{$k}; }
}
' file1 file2
a:2
b:1
c:2
d:0

이 답변의 모든 코드 예제는 동일한 프로그램에 대한 것입니다. 둘 다 동일한 입력에서 동일한 출력을 생성합니다. 그것들은 실질적으로 다시 작성되지도 않았습니다. 이는 약간의 조정만 제외하면 동일한 언어를 사용하는 동일한 논리입니다.

솔루션을 평가할 때 따라야 할 한 가지 축은 나중에 유지 관리를 위해 솔루션으로 돌아가는 것이 얼마나 쉬운가입니다. 이것이 이 한 가지 작업만 수행하는 간단한 도구이고 이를 반복적으로 실행해야 하지만 코드를 다른 것으로 확장해야 할지 의심스럽다면 아마도 두 번째 버전이나 그에 가까운 버전을 사용할 것입니다. 이것이 더 큰 프로그램의 일부라면 첫 번째 프로그램부터 시작하여 더 명시적인 파일 처리(예: ) openclose오류 처리를 추가할 것입니다.

관련 정보