【问题标题】:While using sed, how to remove \n with \t if a line ends with number使用 sed 时,如果一行以数字结尾,如何用 \t 删除 \n
【发布时间】:2016-11-05 05:28:52
【问题描述】:

我有一个文件,其中包含以字母结尾的行和以数字结尾的行。例如,

Integral ionization cross-section for |K| = 0.60
-5.591955866599557e-15  -7.944431558483296e-17i

第一行以数字结尾,第二行以字母结尾。 我想做的是,如果一行以数字结尾,请删除 \n 并在其位置插入 \t。

但我不知道如何在 sed 中执行此操作。我尝试使用sed -i 's/[0-9]\n/\t/',但它也改变了数字。是否可以保持数字不变而只更改行尾?

【问题讨论】:

    标签: bash vim awk sed


    【解决方案1】:

    sed:

    sed '/[0-9]$/ { N; s/\n/\t/; }'
    

    输出:

    Integral ionization cross-section for |K| = 0.60        -5.591955866599557e-15  -7.944431558483296e-17i
    

    要处理以数字结尾的连续行,试试这个:

    sed ':l; /[0-9]$/ { N; s/\n/\t/; bl; }' test.txt
    

    使用 Vim:

    :%s/\d\zs\n/\t/g
    

    awk:

    awk '{ while($0 ~ /[0-9]$/) { getline n; $0 = $0 "\t" n } } 1' test.txt
    

    perl:

    perl -00pe 's/\d\K\n/\t/gs' test.txt
    

    【讨论】:

    • 有一个问题。如果连续 2 行以数字结尾,则只有其中一行会使用制表符连接到下一行。
    • @anishsane 如果这是您对问题的解读,那肯定是。
    【解决方案2】:

    这就是你可以用sed 做到这一点的方法:

    $ sed -i 'N;s/\n/\t/' filename
    

    N 命令是可以匹配换行符的技巧。

    有关N 的解释,请参阅this answer on stackoverflow

    【讨论】:

    • \t替换\n如果一行以数字结尾
    【解决方案3】:

    这可能对你有用(GNU sed):

    sed -r ':a;N;s/([0-9])\n/\1\t/;ta;P;D' file
    

    这一次读取两行,然后用数字后跟制表符替换数字后跟换行符,用另一行填充模式空间并重复。如果替换没有发生,则打印第一行,然后删除并附加另一行。

    【讨论】:

      【解决方案4】:

      sed 用于单行上的简单替换,因此 sed 解决方案将不清楚和/或不可移植和/或低效和/或脆弱。这是一个与这些无关的 awk 解决方案:

      $ awk '{printf "%s%s", $0, (/[0-9]$/ ? "\t" : "\n")}' file
      Integral ionization cross-section for |K| = 0.60        -5.591955866599557e-15  -7.944431558483296e-17i
      

      或者如果您更喜欢简洁而不是清晰:

      $ awk '{ORS=(/[0-9]$/?"\t":"\n")}1' file
      Integral ionization cross-section for |K| = 0.60        -5.591955866599557e-15  -7.944431558483296e-17i
      

      【讨论】:

        【解决方案5】:

        使用 GNU sed:

        sed -Ez 's/([0-9])\n/\1\t/g' file.txt
        

        -z 将导致输入被视为 NUL 分隔而不是(默认)换行符分隔。

        示例:

        % cat foo.txt
        Integral ionization cross-section for |K| = 0.60
        -5.591955866599557e-15  -7.944431558483296e-17i
        Integral ionization cross-section for |K| = 0.60
        -5.591955866599557e-15  -7.944431558483296e-17i
        
        % sed -Ez 's/([0-9])\n/\1\t/g' foo.txt
        Integral ionization cross-section for |K| = 0.60    -5.591955866599557e-15  -7.944431558483296e-17i
        Integral ionization cross-section for |K| = 0.60    -5.591955866599557e-15  -7.944431558483296e-17i
        

        【讨论】:

          【解决方案6】:

          我喜欢用 Perl 来做这种事情:

          perl -pe 's/(?<=\d)\n$/\t/;' <file;
          ## Integral ionization cross-section for |K| = 0.60        -5.591955866599557e-15  -7.944431558483296e-17i
          

          【讨论】:

            猜你喜欢
            • 2022-11-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-07-13
            • 2011-05-25
            • 1970-01-01
            • 2011-10-04
            相关资源
            最近更新 更多