4

このようなファイル data.txt があります。

>1BN5.txt
207
208
211
>1B24.txt
88
92

テキスト ファイルを含むフォルダ F1 があります。

F1 フォルダ内の 1BN5.txt ファイルを以下に示します。

ATOM    421  CA  SER A 207      68.627 -29.819   8.533  1.00 50.79           C 
ATOM    421  CA  SER A 207      68.627 -29.819   8.533  1.00 50.79           C  
ATOM    422  C   SER A 248      70.124 -29.955   8.226  1.00 55.81           C 
ATOM    615  H   LEU B 208       3.361  -5.394  -6.021  1.00 10.00           H
ATOM    616  HA  LEU B 211       2.930  -4.494  -3.302  1.00 10.00           H 
ATOM    626  N   MET B  87       1.054  -3.071  -5.633  1.00 10.00           N  
ATOM    627  CA  MET B  87      -0.213  -2.354  -5.826  1.00 10.00           C 

F1 フォルダ内の 1B24.txt ファイルを以下に示します。

ATOM    630  CB  MET B  87      -0.476  -2.140  -7.318  1.00 10.00           C 
ATOM    631  CG  MET B  88      -0.828  -0.688  -7.575  1.00 10.00           C
ATOM    632  SD  MET B  88      -2.380  -0.156  -6.830  1.00 10.00           S
ATOM    643  N   ALA B  92      -1.541  -4.371  -5.366  1.00 10.00           N  
ATOM    644  CA  ALA B  94      -2.560  -5.149  -4.675  1.00 10.00           C

1BN5.txt ファイルの 207,208,211 (6 列目) を含む行だけが必要です。1BN5.txt ファイルの他の行を削​​除したい。このように、1B24.txt ファイルの 88,92 を含む行だけが必要です。

Desired output

1BN5.txt ファイル

ATOM    421  CA  SER A 207      68.627 -29.819   8.533  1.00 50.79           C
ATOM    421  CA  SER A 207      68.627 -29.819   8.533  1.00 50.79           C 
ATOM    615  H   LEU B 208       3.361  -5.394  -6.021  1.00 10.00           H  
ATOM    616  HA  LEU B 211       2.930  -4.494  -3.302  1.00 10.00           H

1B24.txt ファイル

ATOM    631  CG  MET B  88      -0.828  -0.688  -7.575  1.00 10.00           C
ATOM    632  SD  MET B  88      -2.380  -0.156  -6.830  1.00 10.00           S
ATOM    643  N   ALA B  92      -1.541  -4.371  -5.366  1.00 10.00           N 
4

7 に答える 7

5

を使用する1つの方法がありGNU awkます。次のように実行します:

awk -f script.awk data.txt

内容script.awk

/^>/ {
    file = substr($1,2)
    next
}

{
    a[file][$1]
}

END {

    for (i in a) {

        while ( ( getline line < ("./F1/" i) ) > 0 ) {

            split(line,b)

            for (j in a[i]) {

                if (b[6]==j) {

                    print line > "./F1/" i ".new"
                }
            }
        }

        system(sprintf("mv ./F1/%s.new ./F1/%s", i, i))
    }
}

または、これがワンライナーです。

awk '/^>/ { file = substr($1,2); next } { a[file][$1] } END { for (i in a) { while ( ( getline line < ("./F1/" i) ) > 0 ) { split(line,b); for (j in a[i]) if (b[6]==j) print line > "./F1/" i ".new" } system(sprintf("mv ./F1/%s.new ./F1/%s", i, i)) } }' data.txt


の古いバージョン、より古いバージョンをお持ちの場合はawkGNU Awk 4.0.0次のことを試すことができます。次のように実行します:

awk -f script.awk data.txt

script.awkの内容:

/^>/ {
    file = substr($1,2)
    next
}

{
    a[file]=( a[file] ? a[file] SUBSEP : "") $1
}

END {

    for (i in a) {

        split(a[i],b,SUBSEP)

        while ( ( getline line < ("./F1/" i) ) > 0 ) {

            split(line,c)

            for (j in b) {

                if (c[6]==b[j]) {

                    print line > "./F1/" i ".new"
                }
            }
        }

        system(sprintf("mv ./F1/%s.new ./F1/%s", i, i))
    }
}

または、これがワンライナーです。

awk '/^>/ { file = substr($1,2); next } { a[file]=( a[file] ? a[file] SUBSEP : "") $1 } END { for (i in a) { split(a[i],b,SUBSEP); while ( ( getline line < ("./F1/" i) ) > 0 ) { split(line,c); for (j in b) if (c[6]==b[j]) print line > "./F1/" i ".new" } system(sprintf("mv ./F1/%s.new ./F1/%s", i, i)) } }' data.txt


このスクリプトは、説明したとおりに機能することに注意してください。のようなファイルが現在の作業ディレクトリのフォルダに存在する1BN5.txtことを想定しています。また、元のファイルを上書きします。これが望ましい動作でない場合は、通話を切断してください。HTH。1B24.txtF1system()

結果:

内容F1/1BN5.txt

ATOM    421  CA  SER A 207      68.627 -29.819   8.533  1.00 50.79           C 
ATOM    421  CA  SER A 207      68.627 -29.819   8.533  1.00 50.79           C  
ATOM    615  H   LEU B 208       3.361  -5.394  -6.021  1.00 10.00           H
ATOM    616  HA  LEU B 211       2.930  -4.494  -3.302  1.00 10.00           H 

内容F1/1B24.txt

ATOM    631  CG  MET B  88      -0.828  -0.688  -7.575  1.00 10.00           C
ATOM    632  SD  MET B  88      -2.380  -0.156  -6.830  1.00 10.00           S
ATOM    643  N   ALA B  92      -1.541  -4.371  -5.366  1.00 10.00           N
于 2012-12-11T13:38:45.833 に答える
1

この解決策は、レコード区切り記号を使用していくつかのトリックを実行します。「data.txt」は>レコード区切り記号として使用され、他のファイルは改行を使用します。

awk '
    BEGIN {RS=">"}
    FNR == 1 {
        # since the first char in data.txt is the record separator, 
        # there is an empty record before the real data starts
        next
    }
    {
        n = split($0, a, "\n")
        file = "F1/" a[1]
        newfile = file ".new"
        RS="\n"
        while (getline < file) {
            for (i=2; i<n; i++) {
                if ($6 == a[i]) {
                    print > newfile
                    break
                }
            }
        }
        RS=">"
        system(sprintf("mv \"%s\" \"%s.bak\" && mv \"%s\" \"%s\"", file, file, newfile, file))
    }
' data.txt 
于 2012-12-11T21:47:47.390 に答える
1

既存のファイルから行を削除しようとしないでください。必要な行だけを含む新しいファイルを作成してみてください。

cat 1bn5.txt | awk '$6 == 207 || $6 == 208 || $6 == 211 { print }' > output.txt
于 2012-12-11T12:41:17.977 に答える
1

これにより、F1 のすべてのファイルが「backup」という名前の tmp ディレクトリに移動され、F1 の下に結果の空でないファイルだけが再作成されます。

mv F1 backup &&
mkdir F1 &&
awk '
NF==FNR {
   if (sub(/>/,"")) {
      file=$0
      ARGV[ARGC++] = "backup/" file
   }
   else {
      tgt[file,$0] = "F1/" file
   }
   next
}
(FILENAME,$6) in tgt {
   print > tgt[FILENAME,$6]
}
' data.txt &&
rm -rf backup

空のファイルも必要な場合は簡単な調整であり、バックアップディレクトリを保持したい場合は"&& rm.."、最後に削除するだけです(とにかくテスト中にそれを行います)。

編集:参考までに、これは getline が完全に正しくないというケースを主張できる1つのケースです。構造と意図が残りのファイルとはまったく異なる最初のファイルを解析しているため、1つのファイルを残りのファイルとは異なる方法で解析することはできません後でメンテナンスの頭痛の種を引き起こす:

mv F1 backup &&
mkdir F1 &&
awk -v data="data.txt" '
BEGIN {
   while ( (getline line < data) > 0 ) {
      if (sub(/>/,"",line)) {
         file=line
         ARGV[ARGC++] = "backup/" file
      }
      else {
         tgt[file,line] = "F1/" file
      }
   }
}
(FILENAME,$6) in tgt {
   print > tgt[FILENAME,$6]
}
' &&
rm -rf backup

しかし、ご覧のとおり、スクリプトはもう少し複雑になります (ただし、本体に FNR==NR のテストがないため、わずかに効率的です)。

于 2012-12-12T12:47:37.557 に答える
1

gnu awk を想定して、以下を含むディレクトリからこのコマンドを実行しますdata.txt

awk -F">" '{if($2 != ""){fname=$2}if($2 == ""){term=$1;system("grep "term" F1/"fname" >>F1/"fname"_results");}}' data.txt

これは、ファイル名と検索用語を解析し、内部から をdata.txt呼び出して、 にリストされている各ファイルと用語からの一致を、と呼ばれるの新しいファイルに追加します。grepawkdata.txtF1originalfilename.txt_results

元のファイルを完全に置き換えたい場合は、次のコマンドを実行できます。

grep "^>.*$" data.txt | sed 's/>//' | xargs -I{} find F1 -name {}_results -exec mv F1/{}_results F1/{} \;
于 2012-12-11T17:36:18.870 に答える
0

間違いなく次のような仕事ですawk:

$ awk '$6==207||$6==208||$6==211 { print }' 1bn5.txt
ATOM    421  CA  SER A 207      68.627 -29.819   8.533  1.00 50.79           C 
ATOM    421  CA  SER A 207      68.627 -29.819   8.533  1.00 50.79           C  
ATOM    615  H   LEU B 208       3.361  -5.394  -6.021  1.00 10.00           H
ATOM    616  HA  LEU B 211       2.930  -4.494  -3.302  1.00 10.00           H 

$ awk '$6==92||$6==88 { print }' 1B24.txt
ATOM    631  CG  MET B  88      -0.828  -0.688  -7.575  1.00 10.00           C
ATOM    632  SD  MET B  88      -2.380  -0.156  -6.830  1.00 10.00           S
ATOM    643  N   ALA B  92      -1.541  -4.371  -5.366  1.00 10.00           N 

リダイレクトして出力を保存します。

$ awk '$6==207||$6==208||$6==211 { print }' 1bn5.txt > output.txt
于 2012-12-11T12:44:16.057 に答える
0

一人でここまでできるとは思えませんsed。ファイル data.txt を読み取るにはループが必要です。たとえば、bashスクリプトを使用すると、次のようになります。

#!/bin/bash

# First remove all possible "problematic" characters from data.txt, storing result
# in data.clean.txt. This removes everything except A-Z, a-z, 0-9, leading >, and ..
sed 's/[^A-Za-z0-9>\.]//g;s/\(.\)>/\1/g;/^$/d' data.txt >| data.clean.txt

# Next determine which lines to keep:
cat data.clean.txt | while read line; do
   if [[ "${line:0:1}" == ">" ]]; then
      # If input starts with ">", set remainder to be the current file
      file="${line:1}"
   else
      # If value is in sixth column, add "keep" to end of line
      # Columns assumed separated by one or more spaces
      # "+" is a GNU extension, so we need the -r switch
      sed -i -r "/^[^ ]+ +[^ ]+ +[^ ]+ +[^ ]+ +$line +/s/$/keep/" $file
   fi
done

# Finally delete the unwanted lines, i.e. those without "keep":
# (assumes each file appears only once in data.txt)
cat data.clean.txt | while read line; do
   if [[ "${line:0:1}" == ">" ]]; then
      sed -i -n "/keep/{s/keep//g;p;}" ${line:1}
   fi
done
于 2012-12-11T14:34:08.073 に答える