合并文本文件中的行,使用shell脚本

3
我从shell脚本中调用一个程序,它会创建一个带有以下格式的输出文件:
aaaaa\
bbbbb\
ccccc\

我想把这个改成:

aaaaabbbbbccccc

在VI编辑器中,我可以执行ggVGJ,然后用""替换所有\。但我想通过脚本来完成这个任务。
7个回答

5

以下是使用GNU sed 的一种方法:

sed ':a; N; $!ba; s/\\\n//g; s/\\$//' file

另一种使用 awk 的方法,可能会提供更好的性能:

awk '{ sub ("\\\\$", ""); printf "%s", $0 } END { print "" }' file

结果:

aaaaabbbbbccccc

解释:

awk的解决方案通过替换删除尾随的反斜杠,并printf每行(不带换行符)。END(在脚本末尾执行)然后打印一个换行符。这比sed的解决方案更好,因为它创建了一个名为a的标签,并将下一行输入附加到模式空间中。$!ba表示“如果不是最后一行输入,则跳转到标签a”。第一个替换然后从模式空间中删除每个反斜杠和换行符。第二个替换删除最后的尾随反斜杠。对于小文件,此解决方案应该很快,但与相同文件的awk一样快。虽然...编写速度更快。


谢谢你的答复。但是abc可以是任何东西,而且文件非常长。 - arunmoezhi
@arunmoezhi:添加了一个awk解决方案。希望有所帮助。 - Steve
awk的解决方案可行。谢谢。你能否更新你的答案并加上一些解释。 - arunmoezhi
@arunmoezhi:已添加解释。如果您需要更深入的解释,请告诉我。 - Steve

3

以下是一种使用 sedtr 的方法:

sed 's/\\$//' < sample.txt | tr -d '\n'

如果您想添加换行,您可以在末尾添加 echo:
sed 's/\\$//' < sample.txt | tr -d '\n'; echo

如果您希望整个内容作为一个单元,例如在... && ... || ...结构中使用,则可以像这样将两个步骤分组:
{ sed 's/\\$//' < sample.txt | tr -d '\n'; echo; }

这个有效。谢谢。当我像这样将输出管道到同一个文件中: sed 's/\\$//' < sample.txt | tr -d '\n' | cat > sample.txt 然后在vi中打开它,我会得到[noeol]标志。因此,文件的最后一行没有换行符。 - arunmoezhi
您还可以使用以下命令: sed 's/\\$//' file | tr -d '\n'; echo - Steve

3
我想这个解决方案是最小的:
$ cat tmp.txt
aaaaa\
bbbbb\
ccccc\

$ cat tmp.txt | tr -d "\\\r\n"
aaaaabbbbbccccc

请问您能否解释一下您的解决方案?我猜您是将“\”和换行符替换为“”。 - arunmoezhi
1
我只是从stdin中删除字符\、\r和\n。TR的标志“-d”会导致删除搜索到的字符,而不是用第二组字符替换它们。 - Cyber Oliveira

3

另外一种方式,使用纯 bash:

$ cat file.txt 
aaaaa\
bbbbb\
ccccc\
$ { cat file.txt ; echo; } | while read line; do echo $line; done
aaaaabbbbbccccc
$

这是因为bash的read命令会自动处理\符号的换行(使用-r开关可禁用此行为)。在这个例子中,cat后面的echo是必要的,因为你的示例文本的最后一行以\结尾,因此read命令不认为它已经到达了行末并且不输出任何内容。echo只是在流的末尾插入一个空行来清除这个问题。

2

尝试这行代码;

awk -F'\\\\$' '{printf "%s", $1}END{print ""}' file

2

这是一个十分丑陋的hack,但您可以使用gcc预处理器来实现:

 $ cat file.txt 
 aaaaa\
 bbbbb\
 ccccc\
 $ cat file.txt | gcc -xc -E -P -w - | grep .
 aaaaabbbbbccccc
 $ 

为什么这很危险?如果您输入的文本包含预处理器指令,那么它们将被解释,可能会导致混乱。

1

使用 awksed 中的一个:

sed 's/\\$//g' file | awk '{printf "%s", $1}'

sed 命令移除行末的斜杠。在斜杠后面,$ 表示行末。由于在 sed 中,斜杠被视为元字符,因此需要额外的 \ 进行转义。将 sed 的输出导入到 awk printf 中可将多行打印成一行。 $0 代表整行。


@iamauser:不确定为什么这个被点赞了,但是你永远不应该写一个没有格式规范的printf语句;特别是在打印未知内容的任意字符串时。 - Steve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接