在Unix命令行上简洁便携的"加入"

but*_*utt 74 unix shell

如何将多行连接到一行,使用分隔符表示换行符,并避免使用尾随分隔符,并可选择忽略空行?

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

foo
bar
baz
Run Code Online (Sandbox Code Playgroud)

所需的输出是:

foo,bar,baz
Run Code Online (Sandbox Code Playgroud)

我现在使用的命令:

tr '\n' ',' <foo.txt |sed 's/,$//g'
Run Code Online (Sandbox Code Playgroud)

理想情况下它会是这样的:

cat foo.txt |join ,
Run Code Online (Sandbox Code Playgroud)

什么是:

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

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

Mic*_*ber 122

也许有点令人惊讶的paste是,这是一个很好的方法:

paste -s -d","
Run Code Online (Sandbox Code Playgroud)

这不会处理你提到的空行.为此grep,首先管理您的文本:

grep -v '^$' | paste -s -d"," -
Run Code Online (Sandbox Code Playgroud)

  • 为了增强可移植性,考虑在`paste`命令的末尾添加`-`,只要它预期从`stdin`读取.(某些版本的`paste`,例如BSD,不会从`stdin`读取,除非`-`被明确传递给它.) (12认同)
  • 感谢关于`paste`的提示!我注意到它只允许单字符分隔符,默认情况下它是`\ t`.要完成更长的分隔符(例如`,`):`cat foo.txt | 粘贴-s | sed's /\t /,/ g'` (2认同)

jay*_*ngh 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
Run Code Online (Sandbox Code Playgroud)

要处理空行,您可以删除空行并将其管道传输到上面的单行.

sed -e '/^$/d' file | sed -e :a -e 'N;s/\n/,/;ba'
Run Code Online (Sandbox Code Playgroud)


plh*_*lhn 8

如何使用xargs?

为你的情况

$ cat foo.txt | sed 's/$/, /' | xargs
Run Code Online (Sandbox Code Playgroud)

注意xargs命令的输入限制长度.(这意味着无法处理很长的输入文件.)


myk*_*hal 6

Perl的:

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

或者更短更快,令人惊讶的是:

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

或者,如果你想:

cat data.txt | perl -pe 's/\n/,/ unless eof'
Run Code Online (Sandbox Code Playgroud)

  • 关于这一点的好处是你可以使用任何字符串而不只是一个简单的逗号.接受的答案不太通用.我特别喜欢最后的迭代,虽然我会写它:`perl -pe's/\n /,/除非eof'data.txt`(不需要虚假的猫). (2认同)