特定の文字列を見つけるときに最も近い列を印刷する方法

特定の文字列を見つけるときに最も近い列を印刷する方法

約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=1421687191fck=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行ではなく、例に入れていないもう1つだけですが、問題ではないようです)

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という1つの条件のみが必要です。

この小さなスクリプトを改善する方法や変更を加えることができるすべてのことについてのヒントがあれば良いでしょう。しかし、他のスクリプトも可能です。 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 が点灯している行全体を返します。その後、これを2つのsedにパイプして必要なものを入手してください。

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

最初のsedはfck = 35; fck = 35;前のすべての項目を置き換え(削除)、2番目のsedは次の区切り文字の後のすべての項目を削除します。

しかし、次のようなものが必要なので、行(fmd)で特定の列を選択することもできます。

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

これにより、「fmd =」の前のすべての内容が削除され、次の区切り文字(またはコンマ、処理する必要があるようです)の後のすべての内容が削除されます。

関連情報