タブで区切られたファイル列のテキスト文字列から最初の整数を抽出するには?

タブで区切られたファイル列のテキスト文字列から最初の整数を抽出するには?

私は医療遺伝学の分野で働いており、多くの場合、列の1つ(列5など)にテキスト文字列を持つ区切りテキストファイルがあります。私たちの専門用語は「突然変異」です
c.2458C>Tc.45_46delAAc.749_754delinsTG

同様に、他のファイルでは次のように読み取ることができます。
p.Glu34*またはp.Ala78_Arg80delp.L378Ffs*11

とが必要ですが、省略することもできますc.p.数字以外の文字はいくらでもあります。これらの数字は常に整数であり、通常長さは約1〜14です。

私のファイルのどこかに新しい列を追加したいです。最初のみ最初の例では、2458、45、749などの整数です。次に、この整数をキー値として使用して、ルックアップテーブルで複数の値をルックアップしようとします。

私のファイルの中には70,000行があり、手動で編集することはできません...

解決策は基本的であるほど良いです。 bash、sed、またはawkを使用して実行できますか?

例表は次のとおりです(正しい説明は次のとおりです)。

1       2       3       4       c.2458C>T
a   b   c   d   c.45_46delAA
a1  b2  c3  d4  p.Ala78_Arg80del

(注:列は空白ではなくタブで区切られています。)

フォーマットには仕様があります。ヒトゲノム変異コンソーシアム。どのプログラムもこの形式を使用しませんが(希望します!)、人々は出版物や医療報告書にこの形式を使用します。次の最新形式さまざまな呼び出し形式導入されたので、解析する方が簡単です。

答え1

説明に従って、タブ区切りのファイルを入力とします。例:

$ cat file
1       2       3       4       c.2458C>T       6
a       b       c       d       c.45_46delAA or f
a1      b2      c3      d4      p.Ala78_Arg80del        f6

sedを使う

5番目の列の最初の整数を見つけるには:

$ sed -r 's/([^\t]*\t){4}[^[:digit:]]*([[:digit:]]+).*/\2/' file
2458
45
78

上記はGNUでテストされましたsed。 OSX または他の BSD システムの場合は、以下を試してください。

sed -E 's/([^\t]*\t){4}[^[:digit:]]*([[:digit:]][[:digit:]]*).*/\2/' file

awkを使う

$ awk '{sub(/^[^[:digit:]]*/, "", $5); sub(/[^[:digit:]].*/, "", $5); print $5;}' file
2458
45
78

答え2

@John1024のサンプルテキストを使用すると、これはGNU-awkに固有のものです。

gawk -F '\t' -v OFS='\t' 'match($5, /[[:digit:]]+/, m) {$(++NF) = m[0]} 1' file

生産する

1   2   3   4   c.2458C>T   6   2458
a   b   c   d   c.45_46delAA    or  f   45
a1  b2  c3  d4  p.Ala78_Arg80del    f6  78

またはパール

perl -F'\t' -lane 'print join "\t", @F, $F[4]=~/(\d+)/' file

答え3

Glenn jackmanのGNU / AWKの答えはエレガントですが、より簡単です。

awk 'BEGIN {FS=OFS="\t"} match($5,/[0-9]+/,arr) {print $0,arr[0]}' file

答え4

発生に置き換えることsedができるので、5番目の項目だけが必要です。\t<ab>- 分離[1]他の可能な一致を除いて、フィールドとその中のすべての数字:

sed 's/[^\t0-9]*\([0-9]*\)[^\t]*/\1/5' <infile

別の例をクリップボードにコピーした後、次のようにしました。

xsel -bo | unexpand -a | sed ...

...unexpand -a通行料<タブ>実際のサイズに変換された空間順序<タブ>。そしてそれを印刷して...

1   2   3   4   2458    6
a   b   c   d   45
a1  b2  c3  d4  78  f6

...5番目の列の最初の整数のみを分離します。しかし、これがあなたが望むものであるかどうかはわかりません。 1行の5番目の列の最初の整数だけが必要な場合ははるかに簡単です。(そしてより速い)

<infile \
 cut -f5 | tr -cs '0-9\n' \\t |
 expand -t1,2,4 | cut -d' ' -f-2

...最初cutは5番目です。<タブ>- 分離[2]1行あたりの完全なデータフィールド(フィールドごとに複数の整数を使用して発生する可能性のある問題を回避するため)それtrから<タブ> Ewlinesセットを補完する各-s圧縮文字シーケンスと-c\n0-9 標準番号 [サム]

これは、出力の最初の整数が最初または2番目のフィールドにあることを意味します。最初のフィールドが空であるためです。(<タブ>で開始)または、覚えているようにプレフィックスが付いているかどうかに応じて一連の数字を使用します。だから私のexpand最初と2番目のCD<タブ>- 1 行目、3 行目の位置で行で停止 - 空白で区切られたフィールドのリストを空の最初のフィールドまたは空の 3 番目のフィールドで効果的に入力します。ここでは、cut最初の2つのフィールドを直接出力できます。

 2458
 45
 78

...私が使用した例の結果は次のとおりです。すべて次のように作られたからです。[cp]。だから誰もがリードを持っています。<タブ>しかし、そうでない人は恥ずかしがり、去ります。あるいは、各整数をスペースで区切ってすべての結果を1行に圧縮するには、コマンドに追加して|xargs次のようにします。

2458 45 78

ノート

  1. エスケープは\t問題の標準エスケープではなく、sed文字クラスの文脈ではバックスラッシュと文字がそれぞれ自身を表す[bracket-expression]ため、標準を明確に違反していると主張することもできます。ここでは、読みやすい意図をより明確に表示するためにエスケープを使用していますが、おそらくリテラルを使用する必要があります。\t<タブ>その場で。

  2. cut次の区切り<タブ>デフォルトは文字なので、この場合は一般的な-d [delim-char]オプションは必要ありません。しかし、理由を説明するためにこのメモも追加されました。

  3. リンクで述べたように、POSIX標準では[:digit:]文字クラスに次のものを含める必要があります。0123456789すべてのロケールの文字とソート順序は、クラスの他のインクルードよりも優先されます。 C以外のロケールには、他のローカライズされた数値セットを含めることもできます。 GNUはtr複数バイトで表示されるため、正しく処理できない可能性があります。ただそれにもかかわらず、標準の数値セットはほとんどの場合、最も驚くべき結果ではない可能性が高いため、次のような場合を除いて[:digit:]使用してください。本当に標準アラビア数字セットの文字と一部の文字を一致させたい場合その他ロケールによる数値セットは望ましくないかもしれません。

関連情報