每隔N行删除换行符


16

处理文本时,我需要每两行删除换行符。

示例文本:

this is line one
and this is line two
the third and the
fourth must be pasted too

所需的输出:

this is line one and this is line two
the third and the fourth must be pasted too

我尝试了一个while循环,但是一会儿循环是不好的做法。是否可以使用tr或其他任何命令来执行此操作?


4
标题说“每N行”,但在问题和示例中是“每2行”。大多数答案仅适用于N = 2。您是否正在寻找适合所有N的东西?
JigglyNaga

那是关键。每个人都回答了2行,但我需要使用N = 3或N = 4
jomaweb '16

Answers:


24

paste(也是标准的POSIX简单实用程序,如tr)就是您的工具。

假设您希望这些换行符替换为空格,而不是像示例中那样被删除

paste -d ' ' - - < file

要么:

paste -sd ' \n' file

如果确实要删除它们,请替换' ''\0'

从3中替换2:

paste -sd '  \n' file

3分之一,从第二个开始:

paste -sd '\n \n' file

等等。

另一个好处paste是,它不会使行终止。例如,如果您删除文件中的所有换行符(如tr -d '\n' < filetr '\n' ' ' < file),则最终根本没有任何行,因为需要以换行符结尾的行。因此,通常最好使用paste代替(如paste -sd '\0' filepaste -sd ' ' file),以添加有效文本所必需的尾随换行符。


11

使用现代GNU sed

sed -rz 's/\n([^\n]*\n)/ \1/g' sample.text

awk

awk '{getline line2;print $0, line2}' sample.text

3
这种sed方法意味着将整个文件包含在内存中(前提是它不包含NUL字节),并进行一些昂贵的正则表达式替换。我看不出标准sed 'N;s/\n/ /'方法的好处。
斯特凡Chazelas

6

使用sed如下图所示的这个:

SHW@SHW:/tmp $ cat a
this is line one
and this is line two
the third and the
fourth must be pasted too

SHW@SHW:/tmp $ sed 'N;s/\n/ /' a -i

SHW@SHW:/tmp $ cat a
this is line one and this is line two
the third and the fourth must be pasted too

4

另一种方法是使用 xargs

$ < txt xargs -d '\n' -n 2 echo
this is line one and this is line two
the third and the fourth must be pasted too

哪里

$ cat txt
this is line one
and this is line two
the third and the
fourth must be pasted too

虽然,由于echo每个行都执行一个处理,所以这种解决方案非常过分。因此,除了玩具示例外,还应该首选基于awk / sed或类似方法的解决方案。


1
根据您的echo实现,您还会遇到反斜杠字符或某些以-(例如--help-neneGNU echo)开头的行的问题。另请注意,这-d是GNU扩展。
斯特凡Chazelas

为避免出现问题echo,您可以使用:< txt xargs -d '\n' -n 2 printf -- '%s %s\n'
nyuszika7h,2016年

4

这实际上在vim中非常简单。要加入每行,请使用J命令,然后使用%norm命令将其同时应用于每行。例如

:%norm J<CR>

(以防万一,如果您不熟悉vim,<CR>就意味着输入)

这甚至可以连接任意数量的行。例如,每十行加入

:%norm 9J<CR>

如果您对vim不满意,并且希望将其用作命令行工具,而不是交互式文本编辑器,则可以执行以下操作:

vim myfile -c '%norm J' -c 'wq'

拒绝投票的人会否解释我可以做些什么来改善这个答案?
DJMcMayhem

3
$ awk '{printf "%s%s",$0,(NR%2?" ":"\n")}' sample.txt
this is line one and this is line two
the third and the fourth must be pasted too

$0根据行号NR是奇数还是偶数,这会打印出每行,然后是空格或换行符。

该表达式NR%2?" ":"\n"是一个三元语句。NR%2如果行号为奇数,则表达式的计算结果为true(非零)。在这种情况下,三元表达式返回一个空格。如果计算结果为假(零),则返回换行符。

另类

正如Costas在评论中所建议的:

$ awk '{ORS=(NR%2?" ":RS)}1' sample.txt
this is line one and this is line two
the third and the fourth must be pasted too

在此,三元语句NR%2?" ":RS用于返回空格或输入记录分隔符(RS,默认值=换行符)。此值分配给输出记录分隔符ORS。该1命令末尾的是awk的隐秘速记,用于打印记录。


您仍然可以保存3个字符:()括号和printf;)后的空格
maxschlepzig

1
三元?哦! 'NR%2{printf("%s ",$0);next}1'
科斯塔斯

maxschlepzig的答案和三元声明:'{ORS=(NR%2?" ":RS)}1'
科斯塔斯

@Costas我喜欢。答案已用ORS解决方案更新。
约翰1024

2

通用解决方案,更换 5为所需的行数

$ # eof to ensure last line has newline ending
$ seq 16 | perl -pe 's/\n/ / if ++$i%5 && !eof'
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16

$ # or just use pr
$ seq 16 | pr -5ats' '
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16

1

您可以使用 awk为此:

$ awk '{c="\n"} NR%2 {c=" "} { printf("%s%s", $0, c) } ' txt

它产生:

this is line one and this is line two
the third and the fourth must be pasted too

哪里:

$ cat txt
this is line one
and this is line two
the third and the
fourth must be pasted too

awk动作对每行中,特殊变量执行$0的引用当前行,NR在当前的行号(从1开始)。第二个动作由表达式保护NR%2,它是模运算。因此,c=" "仅在NR%2为true 时才执行,即对于奇数行号。

awk语法是C一样,但是某些元素在某些情况下是可选的-比如分号。


您的c变量是ORS'NR%2{ORS=" "}1;{ORS=RS}'
Costas

0

使用ed

$ cat text
this is line one
and this is line two
the third and the
fourth must be pasted too
this is line one
and this is line two
the third and the
fourth must be pasted too

$ ed text <<'END_ED'
g/./s/$/ /\
j
w text.new
END_ED
164
164

$ cat text.new
this is line one and this is line two
the third and the fourth must be pasted too
this is line one and this is line two
the third and the fourth must be pasted too

ed将针对每个线(编辑命令g应用一组编辑命令到匹配给定正则表达式的每个线的),一个空格字符添加到末尾并与下一行加入。然后将结果文本写入名为的文件text.new


0

用Ruby。

我假设每一n行都是要连接的。假设n = 3输入文件为'infile',结果将写入文件中'outfile'

构造一个文件

Ruby -e "File.write 'infile', <<_
> Line 1
> Line 2
> Line 3
> Line 4
> Line 5
> Line 6
> Line 7
> _"

确认文件内容

ruby -e "p File.read 'infile'"
  # "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\n"

删除换行符并写入文件

ruby -e "File.write 'outfile', File.readlines('infile').
  each_with_index { |line,i| line.chomp! unless (i+1)%3==0 }"

确认内容

ruby -e "puts File.read 'outfile'"
  # ["Line 1", "Line 2", "Line 3\n", "Line 4", "Line 5", "Line 6\n", "Line 7"]

1
好一个 从理论上讲,ruby是关于U&L的话题。但是,由于您是通过在命令行中使用的ruby -e,因此就足够了。
grochmal
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.