如何打开80个字符的文字


5

围绕互联网的许多文本文件在行达到第80个字符之前被分割。我理解那些使用80个字符终端的人是理想的。但是,我喜欢向我的kindle发送更长的文章,但这些文件看起来非常糟糕。看这张图:这是LWN旧问题,自动获取并组装成.mobi

当文本在行中间结束时,80个字符分割清晰可见。

我的问题是:如何打开/取消这些线?当然,“手工”方法是在讨论之外。编辑:让我们澄清:我要求脚本或其他方法可以从Linux终端运行。bash / ruby​​ / python / perl / awk都可以。

另外,假设我只有明文,LWN就是一个例子。


1
问题的一部分是,首先如何完成包装,如何将其与自然换行区分开来?您收到的文本必须已在源端修改,因为它无法由您的客户端重新传输。如果你能回答这个问题,编写一个shell脚本来删除包装的换行符是一件小事。如果你无法区分这两者,那么工作就会变得更加艰难。
Frank Thomas

我想要回流的大部分文字有两个\n`'s when natural break is (and it happens only when new paragraph is created, so there happends to be second newline created). So one null`将没有新行,两个null- 两个新行
SzymonSzydełko2013年

3
你在用什么编辑器?可以“显示CR LF”??? 我认为NotePad ++可以......最体面的文本编辑器可以,然后你可以在chars上进行查找/替换。
Logman 2013年

1
@Logman你也可以使用TextFX插件(以前用Notepad ++,我认为你现在必须从插件管理器中读取它)来包装/解包任意宽度的文本(它将自动检测和处理空白)。
突破

CR?在行的末尾只有LF的...就像在那里我也使用vim / sublimetext / kate(取决于心情)
SzymonSzydełko2013年

Answers:


5

使用的答案fmt似乎是包装文本而不是解开它。

通常,这可能是一个难题。例如,区分早期故意完成的相邻文本行(例如子弹点)和相邻的自由流动文本行可能需要一些上下文。区分跨行和分割单词的带连字符的单词也很难。

然而,散文的一种常见形式是邻近包裹的文本行,形成由单个空换行符分隔的段落。

这可以使用以下内容打开,包括一个内衬:

sed -n '/.+/ H; /^$/ { x; s/\n/ /g; s/$/\n/ ; p}'

或者你可能更喜欢一个小的python脚本,特别是如果你要处理一些特殊情况:

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(' ', ' ')

如果您发现自己添加了特殊的外壳,那么您希望找到换行文本的来源并以非线包裹的形式获取。


是否有BSD sed等效?
Alec Jacobson 2016年

此外,python命令应该print ' '.join(paragraph).replace(' ', ' ')在for循环之后有一个if,如果paragraph不为空则清除最后一个段落。
Alec Jacobson 2016年

是的,很可能。我实际上没有运行此代码。我只是想提供一个非sed解决方案。
2016年

编辑的答案包括Alec Jacobson的建议。
Righ 2017年

1

特殊情况,正如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')

1

我刚刚找到了这篇文章,同时正在寻找使用sed做到这一点的方法。这是我在大部分解包时使用的shell脚本:

# unwrap text with linebreaks in paragraphs and blank lines between paragraphs
# This script reads stdin and writes stdout
# cat is used to read stdin into a here-string so that lnum may be printed at the end, outside of the loop

oline=""
lnum=0

while read aline
do
    lnum=$((++lnum))
    # check for probable blank line by its length, end of paragraph
    if [ ${#aline} -lt 3 ]
        then
        # output concatenated line
        echo "$oline"
        # output blank line
        echo ""
        # prepare for the next paragraph
        oline=""
    else
        # otherwise add it to the unwrapped line
        oline=$(echo $oline|tr -d '\n'|tr -d '\r')
        oline="$oline $aline"
    fi
done <<< "$(cat)"

echo "$lnum"
exit 0

1

我遇到了同样的问题 - 通过电子邮件发送包含80字符的段落正文中的强制换行符的纯文本文件...这些文件在(a)自行换行和(b)换行的设备上看起来很糟糕宽度小于80 ...也就是说,80-字符分割清晰可见,文本在行的中间结束。

如何打开这些线?

根据RaúlSalinas-Monteagudo的建议,使用unix命令行工具'fmt'。将行长度(-w ##)更改为有用的数字。您可以尝试65或55,或尝试1111或更大。

例:

来自气象办公室的这个文件(https://forecast.weather.gov/product.php?site=NWS&issuedby=AT&product=TWO&format=txt&version=1&glossary=0)包含嵌入在段落正文中的硬线。我只想在段落末尾添加换行符。将输出管道输出为'fmt -w 1111'(对于长度小于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

改变外观:

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.

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.