61000列と173行のテキストファイルがあります。 2列ごとにデータをマージしたいです。つまり、1列と2列をマージし、3列と4列をマージし、5列と6列をマージする必要があります。
入力例(タブ区切り):
Ind Pop scaffold1 X scaffold1 X.1 scaffold3 X.2 scaffold4 X.3
a antartica 1 1 1 1 2 2 1 1
b antartica 1 1 1 1 2 1 1 2
c antartica 1 1 1 1 2 1 1 1
d antartica 1 1 1 1 2 1 1 2
e antartica 1 1 1 1 2 1 1 2
f arctic 1 1 1 1 2 1 1 1
g arctic 1 1 1 2 2 1 1 1
h arctic 1 1 1 1 2 1 1 1
I arctic 1 1 1 1 2 1 1 1
j arctic 1 1 1 1 2 1 1 1
希望の出力(タブ区切り):
Ind-Pop scaffold1-X scaffold2-X.1 scaffold3-X.2 scaffold4-X.3
a-antartica 1-1 1-1 2-2 1-1
b-antartica 1-1 1-1 2-1 1-2
c-antartica 1-1 1-1 2-1 1-1
d-antartica 1-1 1-1 2-1 1-2
e-antartica 1-1 1-1 2-1 1-2
f-arctic 1-1 1-1 2-1 1-1
g-arctic 1-1 1-2 2-1 1-1
h-arctic 1-1 1-1 2-1 1-1
I-arctic 1-1 1-1 2-1 1-1
j-arctic 1-1 1-1 2-1 1-1
Rでtidyrパッケージのunity関数を使ってこれをやってみました。次のコマンドを使用して、一度に2つの列をマージできます。
unite(df, newcol, c(scaffold1, X), remove=TRUE)
複数の列を使用してこれを行う方法がわかりません。
R、Perl、またはLinuxのコマンドラインメソッドを使用して非常に感謝します!
答え1
sed -E 's/([^\t]+)\t([^\t]+)/\1-\2/g'
説明する
sed -E 's/foo/bar/g'
:拡張正規表現をsed
使用して実行し、各行を複数回置き換えます。-E
foo
bar
/g
([^\t]+)\t([^\t]+)
[^\t]
:タブではなく、文字長の1つ以上の文字を一致させ、+
それらをグループとしてキャプチャします([^\t]+)
。その後、タブ文字が続き、他のキャプチャグループのタブ以外の文字が続きます。\1-\2
-
:最初のキャプチャグループに置き換え、次に2番目のキャプチャグループに置き換えます。デフォルトではタブを-
。
これがうまくいく理由
sed
「貪欲」です。つまり、できるだけ多くの文字を取得しようとします。したがって、両方のキャプチャグループはできるだけ長く維持しようとします。たとえば、すべてを取得しますa antartica
(に置き換えますa-antartica
)。次回検索が実行されると、antartica
その単語の次のタブで検索が再開されます。だから次のゲームはであり1 1
、に置き換えられます1-1
。これにより、各列ペアについてパターンが繰り返されます。欲+
は重要です。省略すると、各タブのみが変更されるモードです。
答え2
以下は、「file.tsv」入力に使用できるいくつかの方法です。
$ perl -pe 's/\t/("-",$&)[$|--]/ge' file.tsv
ここでは、すべての奇数タブをダッシュに置き換えます。
$ sed -e '
y/\t/\n/
:a;s/\n/-/;s//\t/;ta
' file.tsv
このsedコードは最初にすべてのタブを改行に変更し、次に次第に奇数をダッシュに、偶数をタブに変更します。
$ perl -lpe 's/\t(.*?(?:\t|$))/-$1/g' file.tsv
$ perl -F'\t' -lane '
push @A, join "-", splice @F,0,2 while @F;
print join "\t", splice @A;
' file.tsv
$ perl -F'\t' -nae '($,,$")=("\t", "-");
print map { "@F[2*$_,2*$_+1]" } 0..$#F/2;
' file.tsv