2010-05-26 18 views
9

之前我有格式的文本文件( “INPUT.TXT”):UNIX:更换新线W /结肠,保留换行符EOF

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'。但我试图强调可读性,简单性以及正确工作的正确工具。 'sed'是一个消耗和隐藏换行符的行编辑器。可能不是这份工作的正确工具!

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

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

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

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

现在,我需要从输入的末尾删除冒号。然而,如果我试图通过'sed'传递这个处理后的输入来删除最后的冒号(现在,我认为这是对'sed'的恰当使用),我发现自己有第二个问题。输入不再由换行符终止! 'sed'对所有命令都彻底失败,因为它从来没有发现第一行输入的结尾!

好像在一些输入的末尾添加一个换行符是一个非常非常常见的任务,并且考虑到我本人非常想写一个程序来在C中执行它(这将需要大约八行代码),我无法想象,现在还没有一种简单的方法可以在Linux内核中使用已经可用的工具。

回答

13

这应该做的工作(catecho是不必要的):

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

只有sed使用:

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

猛砸没有任何的外部:

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 

编辑:

这里是纯猛砸另一种方式:

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

编辑2:

这里的又一方式,其确实使用echo

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

我起初很困惑,为什么你作为解决方案张贴我说的确切的东西没有工作,所以我在另一台机器上试了一下。 我当时意识到我需要解决方案的Sun服务器没有使用GNU'sed'。当输入没有终止换行符时,服务器上'sed'的版本会失败,因此,如上所述,为什么我使用'echo'。 ((服务器是工作中的关键任务设备,从未失败,因此从未重新启动,更不用说在几年内更新了。)欢迎来到我的生活。) 虽然shell循环解决方案非常棒,不过。 – Maarx 2010-05-27 21:15:57

+0

/bin/sed on Sun ... ick。/usr/xpg4/bin/sed? – 2010-05-28 16:28:08

1

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

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

老问题,但是

paste -sd: INPUT.txt