【问题标题】:Remove strings by a specific delimiter按特定分隔符删除字符串
【发布时间】:2017-02-22 06:15:51
【问题描述】:

我的文件中有几列,其中第二列有“:”分隔符,我想删除第二列中的第一、第三和第四个字符串,并将第二个字符串留在该列中。但是我有正常的分隔符空间,所以我不知道。

input:

--- 22:16050075:A:G 16050075 A G
--- 22:16050115:G:A 16050115 G A
--- 22:16050213:C:T 16050213 C T
--- 22:16050319:C:T 16050319 C T
--- 22:16050527:C:A 16050527 C A

desired output:

--- 22 16050075 16050075 A G
--- 22 16050115 16050115 G A
--- 22 16050213 16050213 C T
--- 22 16050319 16050319 C T
--- 22 16050527 16050527 C A

Wrong:
cat df.txt | awk -F: '{print $1, $3, $6, $7, $8}'

--- 22 A
--- 22 G
--- 22 C
--- 22 C
--- 22 C

但我做不到。 awk 和 sed 命令可以做到吗?

谢谢。

【问题讨论】:

  • 我尝试了上述方法。它只是成功地将它们分开,但无法选择列。

标签: linux bash awk sed


【解决方案1】:

只需在$2 上使用POSIX 兼容的split() 函数即可

awk '{split($2,temp,":"); $2=temp[2];}1' file
--- 16050075 16050075 A G
--- 16050115 16050115 G A
--- 16050213 16050213 C T
--- 16050319 16050319 C T
--- 16050527 16050527 C A

在分隔符 : 上拆分第 2 列,将 $2 值更新为所需元素 (temp[2]) 并打印其余字段({}1 基于 @ 重新构造所有单个字段987654329@ 并打印出来)。

建议不要使用多个分隔符,因为它会改变各个字段的绝对位置,而split() 可以轻松保留位置并仅提取所需的值。


对于添加新列的更新要求,只需这样做

awk '{split($2,temp,":"); $2=temp[1] FS temp[2];}1' file
--- 22 16050075 16050075 A G
--- 22 16050115 16050115 G A
--- 22 16050213 16050213 C T
--- 22 16050319 16050319 C T
--- 22 16050527 16050527 C A

或者,如果您有 GNU awk/gawk,您可以将其 gensub() 用于基于正则表达式(使用 POSIX 字符类 [[:digit]])的提取作为

awk '{$2=gensub(/^([[:digit:]]+):([[:digit:]]+).*$/,"\\1 \\2","g",$2);}1' file
--- 22 16050075 16050075 A G
--- 22 16050115 16050115 G A
--- 22 16050213 16050213 C T
--- 22 16050319 16050319 C T
--- 22 16050527 16050527 C A

gensub(/^([[:digit:]]+):([[:digit:]]+).*$/,"\\1 \\2","g",$2) 部分仅捕获由: 分隔的前两个字段,其中捕获组\\1\\2 并打印其余字段。

【讨论】:

  • 如果我打印会怎么样 --- 22 16050075 16050075 A G --- 22 16050115 16050115 G A --- 22 16050213 16050213 C T --- 22 16050319 160503219 C5527 --- 22 16050319 160503219 C52067s --- 205019 C5206 >
【解决方案2】:

您也可以尝试以下方法来替代@Inian 更好、更便携的解决方案-

awk -F '[ :]' '{print $1, $3, $6, $7, $8}' file

file 包含您的初始输入。

输出-

--- 16050075 16050075 A G
--- 16050115 16050115 G A
--- 16050213 16050213 C T
--- 16050319 16050319 C T
--- 16050527 16050527 C A

编辑

随着输入文件的变化(增加列号2),上面的命令可以改成给出-

awk -F '[ :]' '{print $1, $2, $3, $6, $7, $8}' file

输出

--- 22 16050075 16050075 A G
--- 22 16050115 16050115 G A
--- 22 16050213 16050213 C T
--- 22 16050319 16050319 C T
--- 22 16050527 16050527 C A

【讨论】:

  • 您错过了第 2 列,只需添加它。
  • @ClaesWikner,OP 更改了输入文件。我现在改变了我的命令。感谢您的提醒。
【解决方案3】:

你也可以使用 sed:

sed -r 's/..:([^:]+)[^ ]+/\1/' file

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 2014-07-03
    • 1970-01-01
    相关资源
    最近更新 更多