【问题标题】:UNIX: Replace Newline w/ Colon, Preserving Newline Before EOFUNIX:用冒号替换换行符,在 EOF 之前保留换行符
【发布时间】:2011-02-24 07:49:03
【问题描述】:

我有一个文本文件(“INPUT.txt”),格式为:

A<LF>
B<LF>
C<LF>
D<LF>
X<LF>
Y<LF>
Z<LF>
<EOF>

我需要重新格式化为:

A:B:C:D:X:Y:Z<LF>
<EOF>

我知道你可以使用“sed”来做到这一点。使用“sed”进行此操作的谷歌点击量达到了 10 亿次。但我试图强调可读性、简单性以及使用正确的工具来完成正确的工作。 'sed' 是一个使用和隐藏换行符的行编辑器。可能不是适合这项工作的工具!

我认为这项工作的正确工具是“tr”。我可以使用以下命令将所有换行符替换为冒号:

cat INPUT.txt | tr '\n' ':'

我已经完成了 99% 的工作。不过,我现在有个问题。通过用冒号替换所有换行符,我不仅在序列末尾得到一个多余的冒号,而且在输入末尾也丢失了回车。它看起来像这样:

A:B:C:D:X:Y:Z:<EOF>

现在,我需要删除输入末尾的冒号。但是,如果我尝试通过“sed”传递这个处理过的输入以删除最后的冒号(我认为现在可以正确使用“sed”),我发现自己遇到了第二个问题。输入不再被换行符终止! 'sed' 对于所有命令都完全失败,因为它永远不会找到第一行输入的结尾!

似乎在某些输入的末尾添加换行符是一项非常非常常见的任务,并且考虑到我自己只是非常想用 C 编写一个程序来完成它(这需要大约八行代码) ,我无法想象没有一种非常简单的方法可以使用 Linux 内核中已经提供给您的工具来执行此操作。

【问题讨论】:

    标签: unix sed append newline


    【解决方案1】:

    这应该可以完成工作(catecho 是不必要的):

    tr '\n' ':' < INPUT.TXT | sed 's/:$/\n/'
    

    仅使用sed:

    sed -n ':a; $ ! {N;ba}; s/\n/:/g;p' INPUT.TXT
    

    没有任何外部的 Bash:

    string=($(<INPUT.TXT))
    string=${string[@]/%/:}
    string=${string//: /:}
    string=${string%*:}
    

    sh 中使用循环:

    colon=''
    while read -r line
    do
        string=$string$colon$line
        colon=':'
    done < INPUT.TXT
    

    使用 AWK:

    awk '{a=a colon $0; colon=":"} END {print a}' INPUT.TXT
    

    或者:

    awk '{printf colon $0; colon=":"} END {printf "\n" }' INPUT.TXT
    

    编辑:

    这是纯 Bash 中的另一种方式:

    string=($(<INPUT.TXT))
    saveIFS=$IFS
    IFS=':'
    newstring="${string[*]}"
    IFS=$saveIFS
    

    编辑 2:

    这是 使用 echo 的另一种方式:

    echo "$(tr '\n' ':' < INPUT.TXT | head -c -1)"
    

    【讨论】:

    • 我起初很困惑,为什么你会发布我所说的确切内容不起作用的解决方案,所以我在另一台机器上尝试了它。然后我意识到我需要解决方案的 Sun 服务器没有使用 GNU 'sed'。当输入没有终止换行时,服务器上的“sed”版本失败,因此,如上所述,我使用“echo”的原因。 ((服务器是工作中的关键任务设备,从未发生过故障,因此多年来从未重新启动,更不用说更新了。欢迎来到我的生活。))不过,shell 循环解决方案非常棒。
    • /bin/sed on Sun...ick。 /usr/xpg4/bin/sed 怎么样?
    【解决方案2】:

    这是另一个解决方案:(假设字符集 ':' 是 八进制 72,例如 ascii)

    perl -l72 -pe '$\="\n" if eof' INPUT.TXT

    【讨论】:

      【解决方案3】:

      老问题,但是

      paste -sd: INPUT.txt
      

      【讨论】:

        猜你喜欢
        • 2011-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多