특정 문자열을 찾을 때 가장 가까운 열을 인쇄하는 방법

특정 문자열을 찾을 때 가장 가까운 열을 인쇄하는 방법

약 12000줄의 파일이 있습니다.

pk=91001011964;fck=85;fcv=true;fpi=1;fci=cacf;fmd=1422745568,;fck=83;fcv=decoccm;fpi=1;fci=cacf;fmd=1423070648,;fck=87;fcv=false;fpi=1;fci=cacf;fmd=1422745568,;fck=86;fcv=true;fpi=1;fci=cacf;fmd=1422745568,;fck=35;fcv=54bed48ad84397433fef0a350d65a893;fpi=1;fci=cacf;fmd=1422745568,;fck=83;fcv=travide;fpi=1;fci=cacf;fmd=1422811693,;fck=88;fcv=true;fpi=1;fci=cacf;fmd=1422745568,;fck=84;fcv=10;fpi=1;fci=cacf;fmd=1422745568;vpi=ppi=1;pci=cacf;pmd=1423070648;pos=null;pod=0;pso=null;psd=0;vos=null
pk=91001045537;fck=86;fcv=true;fpi=1;fci=cacf;fmd=1421428238,;fck=85;fcv=true;fpi=1;fci=cacf;fmd=1421428238,;fck=87;fcv=false;fpi=1;fci=cacf;fmd=1421428238,;fck=88;fcv=true;fpi=1;fci=cacf;fmd=1421428238,;fck=84;fcv=10;fpi=1;fci=cacf;fmd=1421428238,;fck=35;fcv=cd9b9ed4fc167d8007dd9544114bc83f;fpi=1;fci=cacf;fmd=1421428238,;fck=83;fcv=demelog;fpi=1;fci=cacf;fmd=1421557377;vpi=ppi=1;pci=cacf;pmd=1421557377;pos=null;pod=0;pso=null;psd=0;vos=null   
pk=91001440737;fck=86;fcv=true;fpi=1;fci=cacf;fmd=1421687966,;fck=85;fcv=true;fpi=1;fci=cacf;fmd=1421687966,;fck=87;fcv=true;fpi=1;fci=cacf;fmd=1421687966,;fck=88;fcv=true;fpi=1;fci=cacf;fmd=1421687966,;fck=84;fcv=10;fpi=1;fci=cacf;fmd=1421687966,;fck=35;fcv=7360072ca14cb5d5578a3902fbe51792;fpi=1;fci=cacf;fmd=1421687191;fck=78;fcv=de724a544277d79c14d19809fe51ab71;fpi=1;fci=cacf;fmd=1421687966,;fck=83;fcv=demelog;fpi=1;fci=cacf;fmd=1421816564;vpi=ppi=1;pci=cacf;pmd=1421816564;pos=null;pod=0;pso=null;psd=0;vos=null

파일을 구문 분석하고 행 내에서 특정 순서로 특정 문자열 값을 찾은 다음 해당 행에 가장 가까운 열을 인쇄하거나 선택해야 합니다. 문자열 값이 없으면 빈 열이 인쇄됩니다.

내가 가지고 있다고 가정합니다 fck=35. 있는 경우 검색된 문자열과 가장 가까운 fmd를 인쇄합니다. 행 3의 경우 가 됩니다 fck=35;fmd=1421687191. fck=35존재하지 않는 경우 빈 열을 추가하면 됩니다.fck=35;;

내가 를 돌보고 있다고 가정해보자 fck=78. 존재하는 경우 검색된 문자열과 가장 가까운 fmd를 인쇄합니다. 3행에는 가 있고 , fck=78;fmd=1421687966없으면 fck=78빈 열을 추가하여 fck=78;;.

그 외 조건은 다음과 같습니다

For fck=84 look for the next fcv For fck=85 look for the next fcv For fck=86 look for the next fcv For fck=83 look for the next fcv fck=83의 다음 fcv는 naismc, decoide, decccm, travide, travccm 또는 mariccm일 수 있습니다.

예를 들어 3번째 줄을 사용하겠습니다.

fck=35;fmd=1421687191;fck=78;fmd=1421687966;fck=84;fcv=10;fck=85;fcv=true;fck=86;fcv=true;fck=83;fcv=demelog

또는 (fmd 또는 fcv가 없거나 적어도 일부가 누락된 경우: 이 부분은 더 이상 3번째 줄이 아니고 예제에 넣지 않은 또 다른 줄일 뿐이지만 문제가 되지 않을 것 같습니다)

fck=35;;fck=78;;fck=84;fcv=10;fck=85;fcv=true;fck=86;;fck=83;fcv=demelog

나는 awk이것을 또는 에서 할 생각입니다 sed. 하지만 그것이 얼마나 강력한지는 의심스럽고, 지금까지 본 바에 따르면 도움이 되지 않습니다. 아마도 Python이 이것을 할 수 있을 것입니다. 그러나 저는 Python을 처음 접했습니다.

어떤 도움이라도 환영합니다.

내 친구가 이 문제를 해결하는 데 도움을 주었습니다.

awk -F\; -v fck=78 '{for (i=1;i<=NF;i++) if($i=="fck="fck) print "fck="fck";"$(i-1)}' name_of_the_file

보시다시피 위의 모든 조건을 충족해야 할 경우 fck=78이라는 하나의 조건만 필요합니다.

이 작은 스크립트를 개선할 수 있는 방법이나 변화를 만들 수 있는 모든 것에 대한 팁이 있으면 좋을 것입니다. 그러나 다른 스크립트도 가능합니다. Python을 고려하고 있지만 어떻게 해야 할지 모르겠습니다.

티아

답변1

찾고 있는 다양한 문자열이 포함된 파일이 있다고 가정합니다. 이 같은:

fck=35 fmd
fck=78 fcv
bnv=12 fcv

이들 각각에 대해 파일을 검색하고 행이 패턴과 일치하는 경우 fmd문자열 다음의 첫 번째 값과 일치해야 합니다. 그렇다면 Perl에서 다음과 같이 할 것입니다.

#!/usr/bin/env perl

## Open the list of search patterns.
## The script expects it to be the 1st argument.
open(my $list,"$ARGV[0]");
## Read the file and save the patterns
## in the %pat hash.
while (<$list>) {
    ## remove trailing newlines
    chomp;
    ## separate the search pattern from the target
    my @fields=split(/\s+/);

    ## Save the search pattern and accompanying target in
    ## in the hash (%pats). 
    $pats{$fields[0]}=$fields[1];
}

## Open the list of search patterns.
## The script expects it to be the 2nd argument.
open(my $file,"$ARGV[1]");

## Read the file
while (<$file>) {
    ## split the line on ';' into the @fields array
    my @fields=split(/;/);

    ## This is the string that will be printed for
    ## the current line.
    my $outstring="";
    ## Check each of the search patterns against
    ## each of the fields.
    foreach my $pat(keys(%pats)) {
        ## Add the pattern to the outstring
        $outstring.="$pat;";
        ## save all all 1st fmd values that follow
        ## this pattern. 
        my @matches= ( /$pat.+?($pats{$pat}=[^;]+)/g );
        ## Add this pattern's matches to the output string.
        $outstring.= join(";",@matches) . ";";
    }
    ## Print the output string for this line
    print "$outstring\n";
}

예를 들어 위 스크립트를 parser.pl파일에 저장 $PATH하고 실행 가능하게 만들면( chmod 755 ~/bin/parser.pl) 다음과 같이 실행할 수 있습니다.

$ parser.pl list.txt file.txt 
bnv=12;;fck=35;fmd=1422745568,;fck=78;;
bnv=12;;fck=35;fmd=1421428238,;fck=78;;
bnv=12;;fck=35;fmd=1421687191 fmd=1111111111;fck=78;fcv=de724a544277d79c14d19809fe51ab71;

답변2

가장 가까운 열을 찾고 있고 구분 기호를 알고 있다면 grep 및 sed를 사용하면 간단한 작업이 될 것입니다.

grep -e "fck=35" 

fck=35가 켜져 있는 전체 행을 반환합니다. 그런 다음 이것을 두 개의 sed로 파이프하여 원하는 것을 얻으십시오.

grep -e "fck=35" | sed s/.*fck=35;//g | sed s/;.*//g

첫 번째 sed는 fck=35; fck=35; 이전의 모든 항목을 대체하고(제거) 두 번째 sed는 다음 구분 기호 이후의 모든 항목을 삭제합니다.

그러나 다음과 같은 것이 더 필요하기 때문에 라인(fmd)에서 특정 열을 선택할 수도 있기를 원하는 것 같습니다.

grep -e "fck=35" | sed s/.*fmd=/fmd=/g | sed s/[;,].*//g

이렇게 하면 "fmd=" 앞의 모든 내용이 제거되고 다음 구분 기호(또는 쉼표, 처리해야 할 것 같습니다) 뒤의 모든 내용이 제거됩니다.

관련 정보