私の入力ファイルは次のとおりです。
#key string pos(string)
key1 AA000AA000000AAA0A 2, 3, 18, 12
key2 00A00AAA000AAAA00A 3, 18
各キー行の末尾に新しい列(タブ区切り)を追加したいと思います。入力ファイルの列2にある場合、A
新しい列には入力ファイルの列3に指定された場所が含まれます。入力ファイルの列2にaがある場合、0
その場所は新しい列に印刷しないでください。
デフォルトでは、これは望ましい出力です。
#key string pos(string) Apos(string)
key1 AA000AA000000AAA0A 2, 3, 18, 12 2, 18
key2 00A00AAA000AAAA00A 3, 18 3, 18
簡単な説明:
(キー1)
- インデックス2の文字列は、新しい列に
A
->エントリを追加します。2
- インデックス3の文字列には
0
->エントリがあります。3
いいえ新しい列に追加 - インデックス12の文字列には
0
->エントリがあります。12
いいえ新しい列に追加 - インデックス18の文字列は、新しい列に
A
->エントリを追加します。18
私はPythonでこれを行っていますが、いくつかのキーと項目(文字列を処理するにはかなり長い)があり、コマンドライン(より軽い)ソリューションに関するアドバイスを求めると思いました。
私の意見は次のとおりです。
- pos(string) フィールドを分割して、文字列フィールドで検索中のインデックスを取得します。
- 文字列の特定のインデックスにある文字を取得します。
- 陳述書(?)
答え1
次のスクリプトはどうですかawk
?
#!/usr/bin/awk -f
BEGIN {
FS="\t"
print "#key\tstring\tpos(string)\tApos(string)"
}
{
out=""
printf "%s\t",$0
split($2,str,"")
gsub(/ /,"",$3)
split($3,pos,",")
for (i in pos){
if (str[pos[i]]=="A"){
out = out pos[i] ", "
}
}
gsub(/, $/,"",out)
print out
}
たとえば、別の名前で保存しfindA.awk
て実行可能にしますchmod +x findA.awk
。
次に、入力データに対して実行し、出力を新しいファイルにリダイレクトします。
./findA.awk input.txt > output.txt
cat output.txt
#key string pos(string) Apos(string)
key1 AA000AA000000AAA0A 2, 3, 18, 12 2, 18
key2 00A00AAA000AAAA00A 3, 18 3, 18
出力は必要に応じてタブで区切られており、タブの幅がさまざまな文字列の幅と一致しないため、例ほどきれいではありません。
答え2
今はどうしたのかわかりませんが(Pythonコードを見てみると役に立ちます)、次のように、列2の「A」を指す列3要素のリストを作成できます。
[i for i in COLUMN3 if COLUMN2[i]=='A']
これは簡単な質問のように見えますが、おそらく完全には理解できないかもしれません。文字列が反復可能であることを忘れましたか?
答え3
ひどいものperl
:
$ perl -anle '
printf "%s Apos(string)\n",$_ and next if /^#/;
printf "%s",$_;
$len = 12 - length((split(/\s+/,$_,3))[-1]);
for $pos_ss (@F[2..$#F]) {
$char = substr($F[1],int($pos_ss)-1,1);
push @res, int($pos_ss) if $char eq 'A';
}
printf "%@{[12-4+$len]}s\n", join ", ",@res;
@res=();
' file
#key string pos(string) Apos(string)
key1 AA000AA000000AAA0A 2, 3, 18, 12 2, 18
key2 00A00AAA000AAAA00A 3, 18 3, 18
私の解決策と同様に動作します。この回答そして、$len
印刷された最後の列を並べ替えるために必要な型を計算する変数を追加します。