【问题标题】:Column editing and renaming of a tab-delimited table in BashBash 中制表符分隔表的列编辑和重命名
【发布时间】:2018-10-18 16:00:05
【问题描述】:

为这个基本问题道歉,但我很困惑。我有一个名为map.txt 的基本制表符分隔文本文件。文件的第一行是列名,前面是# 字符。请注意,这是一个制表符分隔的文件。这是head map.txt的输出:

#SampleID   BarcodeSequence LinkerPrimerSequence    sample_type Description geneticSampleID
OSBS.087.39.M.32.18.20140227    TCCCTTGTCTCC    CGGCTGCGTTCTTCATCGATGC  soil    Plate 1A1   OSBS_087-M-32-18-20140227-gen
OSBS.048.41.M.37.33.20140227    ACGAGACTGATT    CGGCTGCGTTCTTCATCGATGC  soil    Plate 1A2   OSBS_048-M-37-33-20140227-gen
OSBS.048.23.M.15.31.20140227    GCTGTACGGATT    CGGCTGCGTTCTTCATCGATGC  soil    Plate 1A3   OSBS_048-M-15-31-20140227-gen
OSBS.047.21.M.20.3.20140227 ATCACCAGGTGT    CGGCTGCGTTCTTCATCGATGC  soil    Plate 1A4   OSBS_047-M-20-3-20140227-gen
OSBS.119.23.M.18.38.20140227    TGGTCAACGATA    CGGCTGCGTTCTTCATCGATGC  soil    Plate 1A5   OSBS_119-M-18-38-20140227-gen
OSBS.047.41.M.22.36.20140227    ATCGCACAGTAA    CGGCTGCGTTCTTCATCGATGC  soil    Plate 1A6   OSBS_047-M-22-36-20140227-gen
OSBS.087.41.M.40.21.20140227    GTCGTGTAGCCT    CGGCTGCGTTCTTCATCGATGC  soil    Plate 1A7   OSBS_087-M-40-21-20140227-gen
OSBS.048.21.M.5.11.20140227 AGCGGAGGTTAG    CGGCTGCGTTCTTCATCGATGC  soil    Plate 1A8   OSBS_048-M-5-11-20140227-gen
OSBS.119.39.M.27.5.20140227 ATCCTTTGGTTC    CGGCTGCGTTCTTCATCGATGC  soil    Plate 1A9   OSBS_119-M-27-5-20140227-gen

我想将名称 geneticSampleID 更改为 Name 并将 BarcodeSequence 更改为 Index1。然后,我想删除除新命名的 NameIndex1 列之外的所有列。我希望文件的第一行保留列名NameIndex1,前面是# 字符。在 vim 中更改列名非常简单,但删除列则不然。

期望的输出:

#Index1 Name 
TCCCTTGTCTCC OSBS_087-M-32-18-20140227-gen
ACGAGACTGATT OSBS_048-M-37-33-20140227-gen
GCTGTACGGATT OSBS_048-M-15-31-20140227-gen
ATCACCAGGTGT OSBS_047-M-20-3-20140227-gen
TGGTCAACGATA OSBS_119-M-18-38-20140227-gen
ATCGCACAGTAA OSBS_047-M-22-36-20140227-gen
GTCGTGTAGCCT OSBS_087-M-40-21-20140227-gen
AGCGGAGGTTAG OSBS_048-M-5-11-20140227-gen
ATCCTTTGGTTC OSBS_119-M-27-5-20140227-gen

【问题讨论】:

    标签: bash shell terminal


    【解决方案1】:
    cut -f2,6 inputfile | sed '1{ s/geneticSampleID/Name/; s/BarcodeSequence/Index1/; s/^/#/; }'
    
    1. 仅剪切第 2 列和第 6 列的过滤器
    2. Sed 将geneticSampleId 替换为名称s/.../.../,并将BarcodeSeuqnce 替换为索引,但仅用于第一行1{ .. }
    3. sed 还添加了前面的# 字符s/^/#/
    4. 有一天我会学习 awk!

    onlinegdb 提供实时版本。

    【讨论】:

      【解决方案2】:

      您可以使用awksed 等shell 命令来执行此操作,例如:

      cat map.txt | awk '{ print $2, $7}' | sed 's/BarcodeSequence/#Index1 Name/'
      

      输出:

      #Index1 Name 
      TCCCTTGTCTCC OSBS_087-M-32-18-20140227-gen
      ACGAGACTGATT OSBS_048-M-37-33-20140227-gen
      GCTGTACGGATT OSBS_048-M-15-31-20140227-gen
      ATCACCAGGTGT OSBS_047-M-20-3-20140227-gen
      TGGTCAACGATA OSBS_119-M-18-38-20140227-gen
      ATCGCACAGTAA OSBS_047-M-22-36-20140227-gen
      GTCGTGTAGCCT OSBS_087-M-40-21-20140227-gen
      AGCGGAGGTTAG OSBS_048-M-5-11-20140227-gen
      ATCCTTTGGTTC OSBS_119-M-27-5-20140227-gen
      

      虽然现在我们使用 sed 将 1 个列名称替换为 2 个新名称,但我觉得这很奇怪。所以在这种情况下,我更喜欢 awk-only 方式:

      awk 'BEGIN{ print "#Name", "Index1"} NR>1 { print $2, $7}' map.txt
      

      【讨论】:

      • 将动作NR==1 {$2="Index1"; $6="Name"} 添加到awk 脚本可以消除对sed 的需要。
      • 这非常接近。有一个并发症。代码1A1 等是Description 字段的一部分。完整条目是Plate 1A1。由于空间的原因,这可能很复杂。所需的输出将是 OSBS_087-M-32-18-20140227-gen,当前是 1A1
      • @chepner 你当然是对的。我个人认为这段代码更干净。但这当然是口味问题。
      • @rje 将 6 更改为 7 会打印正确的列,但我不再拥有列名 Index1。仅限name
      • @colin 是的,1 分钟.. :)
      【解决方案3】:

      您可以像这样使用单个awk

      awk 'BEGIN{FS=OFS="\t"; print "Index1", "Name"} NR>1{print $2, $6}' file
      

      Code Demo

      输出:

      Index1  Name
      TCCCTTGTCTCC    OSBS_087-M-32-18-20140227-gen
      ACGAGACTGATT    OSBS_048-M-37-33-20140227-gen
      GCTGTACGGATT    OSBS_048-M-15-31-20140227-gen
      ATCACCAGGTGT    OSBS_047-M-20-3-20140227-gen
      TGGTCAACGATA    OSBS_119-M-18-38-20140227-gen
      ATCGCACAGTAA    OSBS_047-M-22-36-20140227-gen
      GTCGTGTAGCCT    OSBS_087-M-40-21-20140227-gen
      AGCGGAGGTTAG    OSBS_048-M-5-11-20140227-gen
      ATCCTTTGGTTC    OSBS_119-M-27-5-20140227-gen
      

      【讨论】:

      • 某处似乎缺少'。我一直收到一个错误,说这没有关闭。
      • 这在我的 shell 上运行良好,你确定没有复制/粘贴错误。
      • 不再是关闭错误,但输出仅打印 ythe 名称,而不是索引。如果我将$6 更改为$7,我会得到index1 字段,但name 字段是空白的,并且前面没有# 字符。
      • 在“工作演示”中错误的条目位于Name 字段中。第一个条目应该是OSBS_087-M-32-18-20140227-gen
      • 您可以选择您选择的任何答案,但使用 $7 非常容易出错,因为实际上它是您想要的第 6 列。如果您在第 5 列中有 Plate 1A1 abc 怎么办。正确的解决方案是将FSOFS 设置为制表符。
      猜你喜欢
      • 2014-03-08
      • 2013-06-30
      • 1970-01-01
      • 2020-02-09
      • 2023-03-03
      • 2013-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多