简洁便携的“连接”在 Unix 命令行上

发布于 2024-12-21 07:42:20 字数 460 浏览 1 评论 0原文

如何将多行连接成一行,并在换行符所在位置使用分隔符,并避免使用尾随分隔符,并且可以选择忽略空行?

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

foo
bar
baz

所需的输出是:

foo,bar,baz

我现在使用的命令:

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

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

cat foo.txt |join ,

什么:

  1. 最便携、简洁、可读方式。
  2. 使用非标准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:

  1. the most portable, concise, readable way.
  2. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

岛歌少女 2024-12-28 07:42:20

也许有点令人惊讶,paste 是执行此操作的好方法:

paste -s -d","

这不会处理您提到的空行。为此,首先通过 grep 传输文本:

grep -v '^
 | paste -s -d"," -

Perhaps a little surprisingly, paste is a good way to do this:

paste -s -d","

This won't deal with the empty lines you mentioned. For that, pipe your text through grep, first:

grep -v '^
 | paste -s -d"," -
水波映月 2024-12-28 07:42:20

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'

This sed one-line should work -

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

Test:

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

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

To handle empty lines, you can remove the empty lines and pipe it to the above one-liner.

sed -e '/^$/d' file | sed -e :a -e 'N;s/\n/,/;ba'
眼中杀气 2024-12-28 07:42:20

使用 xargs 怎么样?

对于您的情况

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

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

How about to use xargs?

for your case

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

Be careful about the limit length of input of xargs command. (This means very long input file cannot be handled by this.)

ぽ尐不点ル 2024-12-28 07:42:20

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'

Perl:

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

or yet shorter and faster, surprisingly:

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

or, if you want:

cat data.txt | perl -pe 's/\n/,/ unless eof'
晌融 2024-12-28 07:42:20

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

IFS=

如果尾随换行符有问题,您可以使用 printf 而不是 echo

这是通过将 read 将分割的分隔符 IFS 设置为换行符而不是其他空格,然后告诉 read 不要停止读取来实现的直到它到达 nul,而不是通常使用的换行符,并将读取的每个项目添加到数组 (-a) 数据中。然后,在子 shell 中,为了不破坏交互式 shell 的 IFS,我们将 IFS 设置为 , 并使用 扩展数组>*,用 IFS 中的第一个字符分隔数组中的每个项目

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

如果尾随换行符有问题,您可以使用 printf 而不是 echo

这是通过将 read 将分割的分隔符 IFS 设置为换行符而不是其他空格,然后告诉 read 不要停止读取来实现的直到它到达 nul,而不是通常使用的换行符,并将读取的每个项目添加到数组 (-a) 数据中。然后,在子 shell 中,为了不破坏交互式 shell 的 IFS,我们将 IFS 设置为 , 并使用 扩展数组>*,用 IFS 中的第一个字符分隔数组中的每个项目

Just for fun, here's an all-builtins solution

IFS=

You can use printf instead of echo if the trailing newline is a problem.

This works by setting IFS, the delimiters that read will split on, to just newline and not other whitespace, then telling read to not stop reading until it reaches a nul, 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 the IFS of the interactive shell, we set IFS to , and expand the array with *, which delimits each item in the array with the first character in IFS

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

You can use printf instead of echo if the trailing newline is a problem.

This works by setting IFS, the delimiters that read will split on, to just newline and not other whitespace, then telling read to not stop reading until it reaches a nul, 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 the IFS of the interactive shell, we set IFS to , and expand the array with *, which delimits each item in the array with the first character in IFS

情绪 2024-12-28 07:42:20

我需要完成类似的事情,从文件中打印以逗号分隔的字段列表,并且很高兴将 STDOUT 通过管道传输到 xargs 和 ruby​​,如下所示:

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

I needed to accomplish something similar, printing a comma-separated list of fields from a file, and was happy with piping STDOUT to xargs and ruby, like so:

cat data.txt | cut -f 16 -d ' ' | grep -o "\d\+" | xargs ruby -e "puts ARGV.join(', ')"
逆流 2024-12-28 07:42:20

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

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

结果是一个文件,其中日志文件中拆分的行是我的新文件中的一行。

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:

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

The result is a file where lines that were split in the log file were one line in my new file.

泼猴你往哪里跑 2024-12-28 07:42:20

使用 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) 不是标准扩展,并且实用程序本身更面向流,因此它不太可移植。

Simple way to join the lines with space in-place using ex (also ignoring blank lines), use:

ex +%j -cwq foo.txt

If you want to print the results to the standard output, try:

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

To join lines without spaces, use +%j! instead of +%j.

To use different delimiter, it's a bit more tricky:

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

where g/^$/d (or v/\S/d) removes blank lines and s/\n/_/ is substitution which basically works the same as using sed, but for all lines (%). When parsing is done, print the buffer (%p). And finally -cq! executing vi q! command, which basically quits without saving (-s is to silence the output).

Please note that ex is equivalent to vi -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 using sed where in-place parameter (-i) is not standard extension and utility it-self is more stream oriented, therefore it's not so portable.

一生独一 2024-12-28 07:42:20

POSIX 外壳:

( set -- $(cat foo.txt) ; IFS=+ ; printf '%s\n' "$*" )

POSIX shell:

( set -- $(cat foo.txt) ; IFS=+ ; printf '%s\n' "$*" )
是伱的 2024-12-28 07:42:20

我的答案是:

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

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

My answer is:

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

printf is enough. We don't need -F"\n" to change field separator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文