合并第一列和第二列;第 3 和第 4 列等带有分隔符

bio*_*han 0 perl text-processing r

我有一个包含 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
Run Code Online (Sandbox Code Playgroud)

所需的输出(制表符分隔):

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
Run Code Online (Sandbox Code Playgroud)

我尝试使用 tidyr 包的 unite 功能用 R 来完成它。我能够使用以下命令一次合并两列:

     unite(df, newcol, c(scaffold1, X), remove=TRUE)
Run Code Online (Sandbox Code Playgroud)

不确定如何为多列执行此操作。

任何 R 或 perl 或 linux 命令行方法将不胜感激!

Spa*_*awk 5

sed -E 's/([^\t]+)\t([^\t]+)/\1-\2/g'
Run Code Online (Sandbox Code Playgroud)

解释

  • sed -E 's/foo/bar/g':sed使用-E扩展的正则表达式运行,每行替换foobar, 多次/g
  • ([^\t]+)\t([^\t]+): 匹配一个长度[^\t]为一个或多个字符的非制表符+,并将其捕获在一个组中([^\t]+)。后面跟着一个制表符,然后是另一个捕获组中的非制表符字符。
  • \1-\2:用第一个捕获组替换它-,然后是第二个捕获组。本质上,将选项卡替换为 -

为什么这有效

sed是“贪婪的”,即尝试获取尽可能多的字符。因此,两个捕获组将尝试尽可能长。例如,它会抓住所有的a antartica(用 替换它a-antartica)。下次运行搜索时,它已经通过了antartica,在这个词之后的选项卡上再次开始搜索。因此,下一场比赛将是1 1,它将替换为1-1。然后将针对每对列重复此模式。贪心+很重要。如果省略它,该模式将只修改每个选项卡。