![用于perl -00在段落模式下啜饮](https://linux22.com/image/1367961/%E7%94%A8%E4%BA%8Eperl%20-00%E5%9C%A8%E6%AE%B5%E8%90%BD%E6%A8%A1%E5%BC%8F%E4%B8%8B%E5%95%9C%E9%A5%AE.png)
互联网上许多文本文件在行达到第 80 个字符之前就被拆分了。我知道使用 80 个字符终端的人希望这样做。但是我喜欢将较长的文章发送到我的 Kindle,但这些文件在 Kindle 上看起来很糟糕。请看这张图片:
当文本在行中间结束时,80 个字符的分割清晰可见。
我的问题是:如何解开/断开这些线?当然,“手动”方法不在讨论范围内。编辑:让我们澄清一下:我要求的是可以从 Linux 终端运行的脚本或其他方法。bash/ruby/python/perl/awk 都可以。
另外,假设我只有纯文本,LWN 只是一个例子。
答案1
答案fmt
似乎是裹文本而不是展开它。
总的来说,这可能是一个难题。例如,区分故意提前结束的相邻文本行(例如项目符号)和自由流动的相邻文本行可能需要一些上下文。区分跨行拆分的带连字符的单词和拆分的单词也很难。
然而,散文的常见形式是相邻的换行文本形成一个段落,并由一个空换行符分隔。
可以使用以下相当复杂的sed
一行程序来解开它:
sed -n '/.+/ H; /^$/ { x; s/\n/ /g; s/$/\n/ ; p}'
或者你可能更喜欢一个小的 Python 脚本,特别是当你要处理一些特殊情况时:
#!/usr/bin/python3
import sys
paragraph = []
for line in sys.stdin:
line = line.strip()
if line:
paragraph.append(line)
else:
print(' '.join(paragraph).replace(' ', ' '))
paragraph = []
if paragraph:
print(' '.join(paragraph).replace(' ', ' '))
如果您发现自己添加了特殊大小写,那么您希望找到换行文本的来源并以非换行形式获取它。
答案2
我也遇到了同样的问题——通过电子邮件发送纯文本文件(从网站下载),这些文件在段落正文中包含 80 个字符的硬换行符...并且这些文件在 (a) 自行换行且 (b) 换行宽度小于 80 的设备上看起来很糟糕...也就是说,在行中间文本结束时,80 个字符的分割清晰可见。
如何取消这些线的换行?
使用 unix 命令行工具“fmt”,按照 Raúl Salinas-Monteagudo 的建议——并将行长度(-w ##)更改为有用的数字……例如,1111 或更大。
例子:
该气象局的文件(forecast.weather.gov/product.php?site=NWS&issuedby=AT&product=TWO&format=txt&version=1&glossary=0)在每个段落的正文中嵌入了单行换行符。
我只希望在段落末尾换行。
将输出通过管道传输到‘fmt -w 1111’可以解决问题(对于长度少于 1111 个字符的段落):
/usr/本地/bin/w3m-转储'https://forecast.weather.gov/product.php?site=NWS&issuedby=AT&product=TWO&format=txt&version=1&glossary=0' | sed -n '/TWOAT/,/Forecaster/p'| fmt -w 1111
[在代码框架中:]
/usr/local/bin/w3m -dump 'https://forecast.weather.gov/product.php?site=NWS&issuedby=AT&product=TWO&format=txt&version=1&glossary=0' | sed -n '/TWOAT/,/Forecaster/p' | fmt -w 1111
。
管道“fmt -w 1111”改变了这样的外观(在小小的手机屏幕上显得非常粗糙):
The National Hurricane Center is issuing advisories on
Tropical Storm Beryl, located a couple of hundred miles
east of the Lesser Antilles, and on Tropical Storm
Chris, located more than one hundred miles south of the
North Carolina Outer Banks.
Tropical cyclone formation is not expected during the
next 5 days.
对此(段落内没有换行符 - 然后在狭窄的手机屏幕上自动完美显示):
The National Hurricane Center is issuing advisories on Tropical Storm Beryl, located a couple of hundred miles east of the Lesser Antilles, and on Tropical Storm Chris, located more than one hundred miles south of the North Carolina Outer Banks.
Tropical cyclone formation is not expected during the next 5 days.
答案3
特别案例,正如 Att Righ 所说…
我发现这个问题是因为我想“解开”fortune
程序的输出,令人恼火的是,这甚至没有标准化——有些幸运饼干在 78 个字符处换行,有些在 77、76 甚至 75 个字符处换行。
我的脚本尝试通过确定如果行没有在这个确切的长度处换行是否会违反长度限制(即如果它还包含下一行的第一个单词,它是否会太长)来确定换行符是故意插入的还是由于长度限制。作为一个有用的副作用,如果下一行以空格开头,则第一个单词(由空格分隔)是空字符串,因此缩进的段落永远不会合并到它们上面的行。
#!/usr/bin/python3
import sys
import fileinput
lines = list(fileinput.input())
lines = [l.strip('\r\n') for l in lines]
for i, l in enumerate(lines):
# We need to account for 8-char-wide tabulators when calculating our line
# length, but still want to print the original \t characters verbatim
sanitized_line = l.replace('\t', ' '*8)
# Is there a next line?
if i+1 < len(lines):
sanitized_next_line = lines[i+1].replace('\t', ' '*8)
else:
sanitized_next_line = ''
next_line_first_word = sanitized_next_line.split(' ', 1)[0]
if next_line_first_word != '':
extended_line = sanitized_line + ' ' + next_line_first_word
else:
extended_line = sanitized_line
if len(sanitized_line) <= 78 and len(extended_line) > 74:
# This line was wrapped due to 78-char limit => unwrap it!
sys.stdout.write(l + ' ')
else:
sys.stdout.write(l + '\n')
答案4
用于perl -00
在段落模式下啜饮
这使得基本的解包命令变得非常容易:
perl -00 -lpe 's/\n/ /g'
添加多个空间的压缩:
perl -00 -lpe 's/\n/ /g, s/ +/ /g'