【问题标题】:Delete \n characters from line range in text file从文本文件的行范围中删除 \n 个字符
【发布时间】:2014-09-21 02:18:13
【问题描述】:

假设我们有一个 1000 行的文本文件。

我们如何从第 20 行到第 500 行删除换行符(例如用空格替换它们)?

我的尝试:

sed '20,500p; N; s/\n/ /;' #better not to say anything

所有其他行 (1-19 && 501-1000) 应保持原样。

由于我熟悉 sed,因此欢迎使用 awk 或 perl 解决方案,但由于我是 perl 和 awk 新手,请与他们一起解释。

【问题讨论】:

标签: perl awk sed


【解决方案1】:

你可以使用这样的东西(我的例子规模略小:-)

$ cat file
1
2
3
4
5
6
7
8
9
10
$ awk '{printf "%s%s", $0, (2<=NR&&NR<=5?FS:RS)}' file
1
2 3 4 5 6
7
8
9
10

printf 格式说明符中的第二个 %s 被字段分隔符(默认为空格)或记录分隔符(换行符)替换,具体取决于记录编号是否在范围内。

或者:

$ awk '{ORS=(2<=NR&&NR<=5?FS:RS)}1' file
1
2 3 4 5 6
7
8
9
10

根据行号更改输出记录分隔符并打印每一行。

如果需要,您可以使用 awk -v start=2 -v end=5 '...' 传递开始和结束的变量

【讨论】:

  • 我已经使用了第二个示例并且它正在工作,这是最重要的 tnx!
  • @josifoski 产生预期输出的程序是解决方案的起点。考虑如何增强此脚本以执行一些琐碎的操作,例如在每个输出值之前打印输入行号(只需在第一个示例中将 printf "%s%s", $0,... 更改为 printf "%s %s%s", NR, $0,... 或在第二个示例中将 1 更改为 {print NR, $0}) .现在考虑如何修改您选择的 sed 解决方案来做同样的事情。除了单行上的简单替换之外,sed 根本不是正确的工具。
【解决方案2】:

这可能对你有用(GNU sed):

sed -r '20,500{N;s/^(.*)(\n)/\2\1 /;D}' file

或许更易读:

sed ':a;20,500{N;s/\n/ /;ta}' file

【讨论】:

  • 第二个示例末尾缺少单引号?
  • 也缺少 \( 在大括号之前,但是,我选择这个只是因为提到了 sed。努力学习 sed、awk 或 perl。现在 seding :)
  • @josifoski sed 是用于在单行上进行简单替换的出色工具,有用的命令是 s、g 和 p(带 -n)。 1970 年代中期,当 awk 被发明时,它的所有其他语言结构都已过时。我强烈建议您使用已发布的 awk 解决方案来解决此问题以及涉及同时处理多行输入的任何其他问题,并且不要费心尝试学习/使用所有其他 sed 语言结构,因为 awk 替代方案总是更健壮,可移植、可扩展、可维护、更清晰、通常更快且通常更简洁。
  • @ed-morton tnx 寻求建议!
  • @josifoski 不客气。不要误会我的意思,我几乎每天都使用 sed,它非常适合它最擅长的东西,我敢肯定,在 1970 年代初期,它是 ed 的唯一替代品,所有这些构造多行的东西都非常有用但那是很久以前的事了!如果您要进行最琐碎的文本处理之外的任何事情,我建议您阅读 Arnold Robbins 的《Effective Awk Programming, Third Edition》一书。
【解决方案3】:

使用 perl 单行删除换行符:

perl -i -pe 'chomp if 20..500' file

或者用空格代替:

perl -i -pe 's/\R/ / if 20..500' file

说明:

开关

  • -i:编辑&lt;&gt; 文件(如果提供扩展名,则进行备份)
  • -p:为输入文件中的每个“行”创建一个 while(&lt;&gt;){...; print} 循环。
  • -e:告诉perl 在命令行上执行代码。

代码

  • chomp:删除新行
  • 20 .. 500: 如果Range operator .. 在行号 20 到 500 之间

【讨论】:

  • perl编程入门好书,专门解析? @米勒
  • 无论是经验丰富的 Perl 程序员还是初学者,我可能会指出的第一个资源是:Modern Perl Book by chromatic。它不仅教人们如何编写 Perl,还教人们如何写好它,并且可以在线免费获得。
【解决方案4】:

这是一个 perl 版本:

my $min = 5; my $max = 10;
while (<DATA>) {
    if ($. > $min && $. < $max) {
        chomp;
        $_ .= " ";
    }
    print;
}

__DATA__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

输出:

1
2
3
4
5
6 7 8 9 10
11
12
13
14
15

它读入DATA(您可以将其设置为文件句柄或您的应用程序需要的任何内容),并检查行号$.。虽然行号在$min$max 之间,但行尾是chomped 并在行尾添加一个空格;否则,该行将按原样打印。

【讨论】:

  • $_ 是一个“默认”变量——对于许多不同的函数,您不需要指定一个命名变量(例如$i);您可以使用此默认变量。如果您确实想引用它,可以使用$_。在这种情况下,$_ 是我们正在查看的__DATA__ 的当前行。 More information in perlvar.= 表示附加到字符串;在这种情况下,我们在当前行附加一个空格。
猜你喜欢
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 2013-06-05
  • 2014-01-30
  • 2017-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多