2011-12-15 28 views
59

如何将多行连接成一行,并使用新行字符所在的分隔符,并避免尾随分隔符以及(可选)忽略空行?Unix命令行上的简洁和便携式“连接”

例子。考虑一个文本文件,foo.txt,三行:

foo 
bar 
baz 

所需的输出是:

foo,bar,baz 

我现在使用的命令:

tr '\n' ',' <foo.txt |sed 's/,$//g' 

理想情况下是什么像这样:

cat foo.txt |join , 

什么是:

  1. 最便携,简洁,可读的方式。
  2. 使用非标准的unix工具最简洁的方式。

当然我可以写些东西,或者只是使用别名。但我很想知道这些选项。

+0

可能的重复[加入多个行到一个bash](http://stackoverflow.com/questions/2764051/joining-multiple-lines-into-one-with-bash) – 2015-04-01 23:32:45

回答

93

也许令人惊讶的一点,paste是做到这一点的好办法:

paste -s -d"," 

这不会与你提到的空行处理。为此,管你的文字通过grep,第一:

grep -v '^$' | paste -s -d"," - 
+0

@codaddict我也不是,但我必须承认我根本没有发现它 - 我总是需要检查手册页。我绝对好奇看到别人的建议。 – 2011-12-15 16:05:29

+0

嘿,谢谢,我甚至不知道这个命令! – fge 2011-12-15 16:06:50

+0

还有其他的方法,但没有更好的(有趣的是有点bashy)。 – Sorpigal 2011-12-15 16:07:03

4

只是为了好玩,这里是一个全内建解决方案

IFS=$'\n' read -r -d '' -a data < foo.txt ; (IFS=, ; echo "${data[*]}" ;) 

可以使用printf代替echo如果其后的换行符是一个问题。

这是通过设置IFS,分隔符是read将分裂的,只是换行,而不是其他的空白,然后告诉read不停止阅读,直到它到达一个nul,而不是通常使用的换行,并添加每个项目读入阵列(-a)数据。然后,在子shell以免揍交互式壳的IFS,我们设置IFS,和扩大与*阵列,其限定在IFS

12

sed此单与第一字符阵列中的每个项行应当工作 -

sed -e :a -e 'N;s/\n/,/;ba' file

测试:

[jaypal:~/Temp] cat file 
foo 
bar 
baz 

[jaypal:~/Temp] sed -e :a -e 'N;s/\n/,/;ba' file 
foo,bar,baz 

要处理空行,您可以删除空行并将其传送到上面的一行。

sed -e '/^$/d' file | sed -e :a -e 'N;s/\n/,/;ba' 
0

我需要完成类似的东西,从打印文件以逗号分隔的字段列表,并很高兴与管道STDOUT到xargsruby,像这样:

cat data.txt | cut -f 16 -d ' ' | grep -o "\d\+" | xargs ruby -e "puts ARGV.join(', ')" 
5

的Perl:

cat data.txt | perl -pe 'if(!eof){chomp;$_.=","}' 

或还更短和更快的,令人惊讶的:

cat data.txt | perl -pe 'if(!eof){s/\n/,/}' 

,或者,如果你想:

cat data.txt | perl -pe 's/\n/,/ unless eof' 
0

使用ex(也忽略空白行),使用与就地空间加入线条简单的方法:

ex +%j -cwq foo.txt 

如果你想将结果打印到标准输出,请尝试:

ex +%j +%p -scq! foo.txt 

要连接没有空格的行,请使用+%j!而不是+%j

要使用不同的分隔符,它的一些技巧:

ex +"g/^$/d" +"%s/\n/_/e" +%p -scq! foo.txt 

其中g/^$/d(或v/\S/d)移除空行和s/\n/_/是取代基本上工作方式相同使用sed,但对于所有的行(% )。解析完成后,打印缓冲区(%p)。最后-cq!执行vi q!命令,该命令基本退出而不保存(-s用于静默输出)。

请注意ex相当于vi -e

此方法非常便于携带,因为大多数Linux/Unix默认配有ex/vi。而且它比使用sed更加兼容,其中就地参数(-i)不是标准扩展并且它的实用程序更多地面向流,因此它不便携。

7

如何使用xargs?

为你的情况

$ cat foo.txt | sed 's/$/, /' | xargs 

要小心xargs的命令输入的极限长度。 (这意味着很长的输入文件不能由此处理。)

0

我有一个日志文件,其中一些数据被分成多行。发生这种情况时,第一行的最后一个字符是分号(;)。我用下面的命令加入这几行:

for LINE in 'cat $FILE | tr -s " " "|"' 
do 
    if [ $(echo $LINE | egrep ";$") ] 
    then 
     echo "$LINE\c" | tr -s "|" " " >> $MYFILE 
    else 
     echo "$LINE" | tr -s "|" " " >> $MYFILE 
    fi 
done 

结果是一个文件,其中在日志文件中被分开的线在我的新文件中的一行。

-1

我的回答是:

awk '{printf "%s", ","$0}' foo.txt 

printf就足够了。我们不需要-F"\n"来更改字段分隔符。