一定有更好的方法来仅替换单个换行符吗?

一定有更好的方法来仅替换单个换行符吗?

我习惯于每句话写一行,因为我通常将内容编译为 LaTeX,或者以其他格式编写,而换行符会被忽略。我使用空行来指示新段落的开始。

现在,我有一个以这种风格编写的文件,我想以纯文本形式发送。我想删除所有单换行符,但保留双换行符完好无损。这就是我所做的:

sed 's/^$/NEWLINE/' file.txt | awk '{printf "%s ",$0}' | sed 's/NEWLINE/\n\n/g' > linebreakfile.txt

这会用一些我确信不会出现在文件中的文本替换空行:NEWLINE然后它会删除所有换行符awk(我在某些网站上发现了这个技巧),然后它NEWLINE用必需的两个换行符替换了 s 。

这似乎是做一件非常简单的事情的一种冗长的方法。有没有更简单的方法?另外,如果有一种方法可以用单个空格替换多个空格(有时由于某种原因会出现),那也很好。

我使用 emacs,所以如果有一些 emacs 特定的技巧那很好,但我宁愿看到一个纯粹的sed或纯粹的awk版本。

答案1

您可以像这样使用 awk:

$ awk ' /^$/ { print; } /./ { printf("%s ", $0); } ' test

或者,如果您需要在末尾添加额外的换行符:

$ awk ' /^$/ { print; } /./ { printf("%s ", $0); } END { print ""; } ' test

或者,如果您想用换行符分隔段落:

$ awk ' /^$/ { print "\n"; } /./ { printf("%s ", $0); } END { print ""; } ' test

这些 awk 命令利用由模式保护的操作:

/regex/

或者

END

仅当模式与当前行匹配时才会执行以下操作。

并且这些^$.字符在正则表达式中具有特殊含义,其中^匹配行的开头、$结尾和.任意字符。

答案2

使用 awk 或 Perl段落模式逐段处理文件,段落之间用空行分隔。

awk -vRS= '
  NR!=1 {print ""}      # print blank line before every record but the first
  {                     # do this for every record (i.e. paragraph):
    gsub(" *\n *"," "); # replace newlines by spaces, compressing spaces
    sub(" *$","");      # remove spaces at the end of the paragraph
    print
  }
'
perl -000 -pe '             # for every paragraph:
  print "\n" unless $.==1;  # print a blank line, except before the first paragraph
  s/ *\n *(?!$)/ /g;        # replace newlines by spaces, compressing spaces, but not at the end of the paragraph
  s/ *\n+\z/\n/             # normalize the last line end of the paragraph
'

当然,由于这不会解析 (La)TeX,因此它会严重破坏注释、逐字环境和其他特殊语法。您可能想了解一下德特克斯或其他 (La)TeX 到文本转换器。

答案3

(复活一个古老的问题)

这似乎正是fmtpar的用途 - 段落重新格式化。像您一样(也像许多程序一样),他们将段落边界定义为一个(或多个)空行。尝试通过其中之一管道传输文本。

fmt是一个标准的 unix 实用程序,可以在 GNU Coreutils 中找到。

par是 Adam M. Costello 编写的一个大大增强的fmt版本,可以在以下位置找到:http://www.nicemice.net/par/(它也被打包用于多个发行版,包括 debian - 我在 1996 年 1 月将它打包为 debian,尽管现在有一个新的 pkg 维护者。)。

答案4

如果我理解正确的话,空行意味着两个连续的换行符,\n\n.

如果是这样,一种可能的解决方案是消除所有单独出现的换行符。

在 Perl 中,前瞻断言是实现此目的的一种方法:

$ perl -0777 -i -pe 's/\n(?=[^\n])//g' test
  • -0777标志有效地将整个文件合并为单个字符串
  • -p告诉 perl 默认打印它正在处理的字符串
  • -i指定就地编辑
  • 全局匹配确保处理所有单个换行符出现

相关内容