简洁便携的“连接”在 Unix 命令行上
如何将多行连接成一行,并在换行符所在位置使用分隔符,并避免使用尾随分隔符,并且可以选择忽略空行?
例子。考虑一个文本文件 foo.txt
,包含三行:
foo
bar
baz
所需的输出是:
foo,bar,baz
我现在使用的命令:
tr '\n' ',' <foo.txt |sed 's/,$//g'
理想情况下它会是这样的:
cat foo.txt |join ,
什么:
- 最便携、简洁、可读方式。
- 使用非标准unix工具的最简洁的方式。
当然我可以写一些东西,或者只是使用别名。但我有兴趣了解这些选项。
How can I join multiple lines into one line, with a separator where the new-line characters were, and avoiding a trailing separator and, optionally, ignoring empty lines?
Example. Consider a text file, foo.txt
, with three lines:
foo
bar
baz
The desired output is:
foo,bar,baz
The command I'm using now:
tr '\n' ',' <foo.txt |sed 's/,$//g'
Ideally it would be something like this:
cat foo.txt |join ,
What's:
- the most portable, concise, readable way.
- the most concise way using non-standard unix tools.
Of course I could write something, or just use an alias. But I'm interested to know the options.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
也许有点令人惊讶,
paste
是执行此操作的好方法:这不会处理您提到的空行。为此,首先通过
grep
传输文本:Perhaps a little surprisingly,
paste
is a good way to do this:This won't deal with the empty lines you mentioned. For that, pipe your text through
grep
, first:此
sed
一行应该可以工作 -sed -e :a -e 'N;s/\n/,/;ba' file
测试:
,您可以删除空行并将其通过管道传输到上面的单行。
This
sed
one-line should work -sed -e :a -e 'N;s/\n/,/;ba' file
Test:
To handle empty lines, you can remove the empty lines and pipe it to the above one-liner.
使用 xargs 怎么样?
对于您的情况
请注意 xargs 命令输入的限制长度。 (这意味着无法处理很长的输入文件。)
How about to use xargs?
for your case
Be careful about the limit length of input of xargs command. (This means very long input file cannot be handled by this.)
Perl:
或者更短更快,令人惊讶的是:
或者,如果你想要的话:
Perl:
or yet shorter and faster, surprisingly:
or, if you want:
只是为了好玩,这里有一个全内置解决方案,
如果尾随换行符有问题,您可以使用
printf
而不是echo
。这是通过将
read
将分割的分隔符IFS
设置为换行符而不是其他空格,然后告诉read
不要停止读取来实现的直到它到达nul
,而不是通常使用的换行符,并将读取的每个项目添加到数组 (-a
) 数据中。然后,在子 shell 中,为了不破坏交互式 shell 的IFS
,我们将IFS
设置为,
并使用扩展数组>*
,用IFS
中的第一个字符分隔数组中的每个项目Just for fun, here's an all-builtins solution
You can use
printf
instead ofecho
if the trailing newline is a problem.This works by setting
IFS
, the delimiters thatread
will split on, to just newline and not other whitespace, then tellingread
to not stop reading until it reaches anul
, instead of the newline it usually uses, and to add each item read into the array (-a
) data. Then, in a subshell so as not to clobber theIFS
of the interactive shell, we setIFS
to,
and expand the array with*
, which delimits each item in the array with the first character inIFS
我需要完成类似的事情,从文件中打印以逗号分隔的字段列表,并且很高兴将 STDOUT 通过管道传输到 xargs 和 ruby,如下所示:
I needed to accomplish something similar, printing a comma-separated list of fields from a file, and was happy with piping STDOUT to
xargs
andruby
, like so:我有一个日志文件,其中一些数据被分成多行。发生这种情况时,第一行的最后一个字符是分号 (;)。我使用以下命令加入了这些行:
结果是一个文件,其中日志文件中拆分的行是我的新文件中的一行。
I had a log file where some data was broken into multiple lines. When this occurred, the last character of the first line was the semi-colon (;). I joined these lines by using the following commands:
The result is a file where lines that were split in the log file were one line in my new file.
使用
ex
(也忽略空行)就地连接带有空格的行的简单方法,请使用:如果要将结果打印到标准输出,请尝试:
要连接不带空格的行,请使用
+%j!
而不是+%j
。要使用不同的分隔符,有点棘手:
其中
g/^$/d
(或v/\S/d
)删除空行和s/ \n/_/
是替换,其工作原理与使用sed
基本相同,但适用于所有行 (%
)。解析完成后,打印缓冲区 (%p
)。最后-cq!
执行 viq!
命令,该命令基本上退出而不保存(-s
是静默输出)。请注意,
ex
相当于vi -e
。这种方法非常便于移植,因为大多数 Linux/Unix 都默认附带
ex
/vi
。它比使用sed
更具兼容性,其中就地参数 (-i
) 不是标准扩展,并且实用程序本身更面向流,因此它不太可移植。Simple way to join the lines with space in-place using
ex
(also ignoring blank lines), use:If you want to print the results to the standard output, try:
To join lines without spaces, use
+%j!
instead of+%j
.To use different delimiter, it's a bit more tricky:
where
g/^$/d
(orv/\S/d
) removes blank lines ands/\n/_/
is substitution which basically works the same as usingsed
, but for all lines (%
). When parsing is done, print the buffer (%p
). And finally-cq!
executing viq!
command, which basically quits without saving (-s
is to silence the output).Please note that
ex
is equivalent tovi -e
.This method is quite portable as most of the Linux/Unix are shipped with
ex
/vi
by default. And it's more compatible than usingsed
where in-place parameter (-i
) is not standard extension and utility it-self is more stream oriented, therefore it's not so portable.POSIX 外壳:
POSIX shell:
我的答案是:
printf
就足够了。我们不需要-F"\n"
来更改字段分隔符。My answer is:
printf
is enough. We don't need-F"\n"
to change field separator.