最初と2番目の列を区切り記号にマージします。

最初と2番目の列を区切り記号にマージします。

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使用して実行し、各行を複数回置き換えます。-Efoobar/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

関連情報