私はMedicalGeneticsで働いており、多くの場合、区切り文字で区切られたテキストファイルがあり、1つの列(例:列5)に「突然変異」を含むテキスト文字列があります。c.2458C>T
またはc.45_46delAA
またはc.749_754delinsTG
同様に、別のファイルでは次のようになります。p.Glu34*
またはp.Ala78_Arg80del
またはp.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
(注:列はスペース区切りではなく、タブ区切りです)
ヒトゲノム変異学会 によるこのフォーマットの仕様があります。この形式を使用するプログラムはありませんが(私は願っています!)、人々は出版物や医療レポートで使用しています。 Variant Call Format などの新しい形式が導入されました。これらははるかに解析可能です。
glennjackmanのGNU/AWKの答えはエレガントですが、もう少し簡単に言えば
awk 'BEGIN {FS=OFS="\t"} match($5,/[0-9]+/,arr) {print $0,arr[0]}' file
あなたの説明に基づいて、入力として、次のようなタブ区切りのファイルがあるとします。
$ 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
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 '{sub(/^[^[:digit:]]*/, "", $5); sub(/[^[:digit:]].*/, "", $5); print $5;}' file
2458
45
78
@ 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
Perl -F'\t' -lane 'print join "\t", @F, $F[4]=~/(\d+)/' file
sed
を使用すると、オカレンスで置き換えることができます-したがって、5番目を要求するだけです<\t
ab>-区切り [1] フィールドと、他の可能な一致を除外することによるその中の任意の数:
sed 's/[^\t0-9]*\([0-9]*\)[^\t]*/\1/5' <infile
ここで他の例をクリップボードにコピーした後、次のようにしました。
xsel -bo | unexpand -a | sed ...
... to unexpand
-a
ll <tab>-サイズのスペースシーケンスを実際の<tab>に。そしてそれは印刷されました...
1 2 3 4 2458 6
a b c d 45
a1 b2 c3 d4 78 f6
...これは5番目の列の最初の整数を分離するだけです。しかし、それがあなたが望むものかどうかはわかりません。行の5番目の列の最初の整数だけが必要な場合は、はるかに簡単です(そしてはるかに高速です)。
<infile \
cut -f5 | tr -cs '0-9\n' \\t |
expand -t1,2,4 | cut -d' ' -f-2
...最初のcut
s5番目の<tab>-区切り [2] 1行あたりのデータフィールド全体(フィールドあたりの複数の整数によって引き起こされる可能性のある問題を回避するため)その後、tr
anslatesを1つに<tab> every -s
queezedシーケンスの文字-c
\n
ewlinesおよび0-9
標準数字 のセットの補足 [3]。
これは、出力では、最初の整数が最初のフィールドまたは2番目のフィールドのいずれかにあることを意味します-最初のフィールドが空になっているため(<tab>が主導)または数字シーケンス(お気づきのように接頭辞が付いていました。したがって、私はexpand
1番目と2番目のcd <tab>-行の位置を1つのスペースに停止し、3番目をスペースに停止します-これにより、スペースのリストが効果的に埋められます-空の最初のフィールドまたは空の3番目のフィールドを持つようにフィールドを区切ります。そこから、最初の2つのフィールドをcut
することができます。
2458
45
78
...すべてが[cp]。でリードされていたため、使用した例の結果でした。したがって、すべてがリード<tab> sでしたが、そうでないものはずらされていました。左に。さらに、すべての結果を1行に凝縮し、各整数を1つのスペースで区切るには、コマンドに|xargs
を追加して、代わりに次のようにします。
2458 45 78
メモ
\t
エスケープは、sed
が関係する標準のエスケープではないことに注意してください。また、[bracket-expression]
文字クラスのコンテキストでは、\
の標準とは明らかに反対です。 SOMECODE] _backslash文字とt
文字は、それぞれ自分自身を表す必要があります。ここでは、読みやすい意図をより明確に示すためにエスケープを使用しましたが、代わりにリテラル<tab>を使用する必要があります。
cut
はデフォルトで<tab>文字で区切られているため、この場合、一般的な-d [delim-char]
オプションは不要ですが、理由を説明するためにこのメモも追加しました。
リンクに記載されているように、POSIX標準では、[:digit:]
文字クラスにすべてのロケールで123456789文字が含まれ、その並べ替え順序で、そのクラスの他の包含よりも先に並べ替えられる必要があります。 。非Cロケールには、他のローカライズされた数字セットも含まれる場合があります-a GNU tr
は、複数のバイトで表される可能性があるため、おそらく適切に処理されません-しかしのみとにかくほとんどの場合、標準の数字セットは最も驚くべき結果ではない可能性が高いので、間違いなく標準のアラビア数字セットといくつかの文字の両方の文字を一致させたい場合を除いて、[:digit:]
を使用しますotherロケールに依存する数字のセットはおそらくお勧めできません。