【问题标题】:Why is this code not replacing spaces with newlines?为什么这段代码没有用换行符替换空格?
【发布时间】:2016-11-30 00:32:47
【问题描述】:

我有一个这样的文件:

17336   GRMZM2G000118   GRMZM2G000118  
190207  GRMZM2G404941  GRMZM2G404922   GRMZM2G104854   
307596  GRMZM5G800488   GRMZM5G800488 GRMZM2G152059   GRMZM2G152059   GRMZM2G152028   GRMZM2G152028

空格分隔的行
我试图从第二个字段剪切字段直到结束,并将其转换为一列:
输出应该是

GRMZM2G000118
GRMZM2G000118
GRMZM2G404941
GRMZM2G404922   
GRMZM2G104854
...

使用这个命令:

cut -f 2- < input.txt | tr " "  "\n" > new_file.txt

但它不起作用

解决它的唯一命令工作是:

 awk '{for(i=2;i<=NF;++i)print $i}'  

或者

 sed  's/\s\+/\n/g'

我的问题是为什么第一种方法不起作用?

【问题讨论】:

  • 这可能与您有多个空格有关。您可能需要预先挤压它们:tr -s ' ' &lt; file | cut -d' ' -f2-.
  • 它被接受为答案谢谢

标签: bash awk sed cut tr


【解决方案1】:

这样做:

cut -d' ' -f2- &lt;input.txt | tr " " "\n" &gt; new_file.txt

编辑:
说明:您需要为您的字段添加分隔符。

【讨论】:

    【解决方案2】:

    以下命令对我有用(假设分隔符是空格)。

    cut -d " " -f 2- &lt;input.txt | tr " " "\n" &gt;new_file.txt

    GRMZM2G000118
    GRMZM2G000118
    GRMZM2G404941
    GRMZM2G404922
    GRMZM2G104854
    GRMZM5G800488
    GRMZM5G800488
    GRMZM2G152059
    GRMZM2G152059
    GRMZM2G152028
    GRMZM2G152028

    您能否添加更多信息,例如您使用的是什么分隔符?

    【讨论】:

      【解决方案3】:

      cut 默认情况下假定字段由单个制表符分隔。无法在每个字段之间指定可变数量的空格,这似乎是您在输入数据中所拥有的。

      我个人建议使用您在问题中显示的 awk 脚本或类似的东西。

      【讨论】:

        【解决方案4】:

        我建议使用这个 awk:

        awk -v OFS="\n" '{sub(/^[[:space:]]*[^[:space:]]*[[:space:]]*/, ""); $1=$1} 1' file
        
        GRMZM2G000118
        GRMZM2G000118
        GRMZM2G404941
        GRMZM2G404922
        GRMZM2G104854
        GRMZM5G800488
        GRMZM5G800488
        GRMZM2G152059
        GRMZM2G152059
        GRMZM2G152028
        GRMZM2G152028
        

        sub 函数和^[[:space:]]*[^[:space:]]*[[:space:]]* 用于从每一行中删除第一列。

        使用cut 会给多个空格带来问题,因为它会将它们转换为多个换行符。

        【讨论】:

        • 与 OP 在问题中使用的简单循环相比,似乎需要付出很多努力!
        • 嗯,我认为使用单个 sub 比使用循环更好
        • sed 's/\s\+/\n/g' 将完成这项工作,而不是所有的努力,但问题仍然是为什么 tr " " "\n" 不能与 cut 一起工作跨度>
        • 我已经回答了为什么cut + tr 由于多个空格而无法正常工作。您的 sed 命令不会跳过每一行的第一列,而是留下多个换行符。
        • 另外,由于 \s\n,sed 命令是 GNU 特定的,因此它不适用于所有系统。
        【解决方案5】:

        我有这样的文件:

        17336   GRMZM2G000118   GRMZM2G000118  
        190207  GRMZM2G404941  GRMZM2G404922   GRMZM2G104854   
        307596  GRMZM5G800488   GRMZM5G800488 GRMZM2G152059   GRMZM2G152059   GRMZM2G152028   GRMZM2G152028
        

        由空格分隔的行我试图从第二个中剪切字段 字段直到结束,并将其转换为一列:输出应为

        GRMZM2G000118
        GRMZM2G000118
        ...
        

        使用这个命令:

        cut -f 2- < input.txt | tr " "  "\n" > new_file.txt
        

        我的问题是为什么第一种方法不起作用?

        这里有两个问题:

        • cut 的默认分隔符是制表符。
        • cut 不会将多个空格挤在一起,这与awk 的作用相反。

        要解决第一个问题,请将分隔符设置为-d ' '。要解决第二个问题,请使用tr -s ' ' 挤压空格:

        $ echo "hello     how are you" | cut -f2-
        hello     how are you
        $ echo "hello     how are you" | cut -d' ' -f2-
            how are you
        $ echo "hello     how are you" | tr -s ' ' | cut -d' ' -f2-
        how are you
        

        你的命令应该是:

        tr -s ' ' < input.txt | cut -d ' ' -f 2- | tr " "  "\n" > new_file.txt
        

        所以现在你有一堆命令,是时候转移到 awk 版本了:)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-02-05
          • 2011-07-01
          • 2015-08-31
          • 2016-01-16
          • 2016-01-11
          • 2019-10-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多