【问题标题】:awk or sed help for munging first line of a CSV or TSV fileawk 或 sed 帮助处理 CSV 或 TSV 文件的第一行
【发布时间】:2013-07-20 17:07:43
【问题描述】:

我一直在搞乱 awk,因为我认为使用这个工具来处理制表符分隔或 csv 文件的标题要简单得多..

我有两种类型的文件(逗号或制表符分隔),我想做的就是将标题 (NR =1) 修改为:

  1. 降低所有单词的大小写
  2. 用下划线替换每个空格 字段名称.. 例如。将癌症类型更改为 *cancer_type*

癌症类型、组装版本、染色体、染色体 开始,染色体结束

到目前为止,我所做的只是列出第一行

awk 'NR == 1' test2.csv

好吧,我很茫然。无论如何,我可能会在进行一些下游修改之前运行此脚本(sed 或 awk)。

任何帮助(或指向我一个好的教程/一个班轮)将不胜感激。

编辑

您好,我应该编辑以澄清这一点。 我将从一个文件开始,并以相同的文件结束,但标题已更改。

我可以获得两个版本的文件。

CSV

癌症类型、组装版本、染色体、染色体起始、 染色体末端

之后:

cancer_type,assembly_version,染色体,chromosome_start, 染色体末端

TSV

癌症类型\t 组装版本\t 染色体\t 染色体开始\t 染色体末端

之后:

cancer_type\t 组装版本\t 染色体\t 染色体开始\t 染色体末端

话虽如此,我认为方法几乎奏效了..

编辑 2 操作系统是 OS X 10.7.+

【问题讨论】:

    标签: bash sed awk


    【解决方案1】:

    GNU 代码

    sed -r '1 {s/.*/\L&/;s/\b\s\b/_/g}' infile>outfile
    

    $ echo Cancer Type, Assembly Version, Chromosome, Chromosome start, Chromosome end|sed -r '1 {s/.*/\L&/;s/\b\s\b/_/g}' 癌症类型、装配版本、染色体、染色体开始、染色体结束

    【讨论】:

    • 恕我直言,\s 不行。输入字符串可以由, 或制表符分隔。我认为\s 也将替换标签。
    • @TrueY 嗯,此刻,单词之间有两个非单词字符。通常将逗号更改为制表符是一个非消耗过程。如果发生这种情况(消耗一个字符),则必须更改正则表达式。正则表达式仅适用于给定问题。
    • 然后改成文字空间。
    • 只有在对即将到来的制表符分隔格式有可靠的陈述时,此时更改正则表达式才有意义。我认为,从 CSV 更改为制表符分隔不会删除某些字符。
    • 我想差不多了。虽然它应该在 infile 上工作。我想做 infile 的原因之一是因为这些文件可以变得大于 10gb ..
    【解决方案2】:

    如果您只想修改标题并按原样打印剩余的行,请尝试使用GNU awk

    awk 'BEGIN{FS=OFS=","}NR==1{$0=tolower($0);gsub(/\y \y/,"_",$0)}1' csv 
    

    【讨论】:

      【解决方案3】:

      如果我理解得很好,OP 想要替换原始文件的标题,而不仅仅是将结果打印到控制台。

      起初我尝试使用 解决它,因为我更了解它。但是 没有就地编辑功能,所以需要一些 解决方法:

      # Unsafe hack
      #{ rm infile; awk 'NR==1{...}1' >infile;} <infile
      #Ed Morton's correction
      awk 'NR==1{...}1' infile >tmp && mv tmp infile
      

      这可行,但它使用 1 个额外的 fork 来执行 rm 命令。最好使用就地编辑。 支持此功能。用perl有点矫枉过正,所以我稍微修正了一下captha解决方案:

      sed -i '1{s/\b \b/_/g;s/[[:upper:]]/\L&/g;}' infile
      

      之前的infile:

      Cancer Type, Assembly Version, Chromosome, Chromosome start, Chromosome end
      One 1,Two 2
      

      infile 之后:

      cancer_type, assembly_version, chromosome, chromosome_start, chromosome_end
      One 1,Two 2
      

      【讨论】:

      • gawk 有就地编辑功能,请看herept.#6
      • @captcha:谢谢!我不知道!
      • cmd &gt; infile &lt; infile 从来都不是一个好主意。初始的rm 完全没有必要,因为cmd &gt; foo 会在启动时截断foo。 sedperl 的“就地”编辑功能与执行 shell 重定向相同,因此在实际运行时行为方面没有任何收获。
      • 无论它是否有效(恕我直言,在一个或两个系统上尝试它并不能证明它通常有效!),该代码比awk '...' file &gt; tmp &amp;&amp; mv tmp file 清晰得多。
      • @EdMorton:你完全正确!你的版本不仅更干净,而且更安全!代码已更正!
      【解决方案4】:

      也许我不完全理解你的问题,但据我了解这应该可以解决它:

      head -1 test2.csv | sed -e 's/\(.*\)/\L\1/' -e 's/ /_/g' > tmp.txt
      tail -n +2 test2.csv >> tmp.txt
      
      • head 选择第一行
      • 第一个 sed 选项将所有内容变为小写
      • 第二个sed 选项将所有空格转换为下划线
      • tail 打印从第 2 行开始的所有内容

      tmp.txt 现在包含完整的结果。

      【讨论】:

      • 嗨..这似乎有效,但它不能替换 csv 文件中的标题行?另外,您需要对制表符分隔的文件而不是 csv 进行哪些修改?
      • @prussiap 查看我对答案的更新。 sed 不关心分隔符,它只是解析和替换,即你可以选择任何你想要的分隔符。
      • 恕我直言,这有点过于复杂了。 sed 支持就地编辑。
      【解决方案5】:

      大家好,这两个命令都有效,但对于 OS X,您必须这样做

      brew install gnu-sed
      

      然后运行你的 sed 命令

      gsed -i '1{s/\b \b/_/g;s/[[:upper:]]/\L&/g;}' infile
      

      魔法.. 谢谢大家。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-23
        • 1970-01-01
        • 1970-01-01
        • 2011-04-02
        相关资源
        最近更新 更多