AWK:将行换行为 72 个字符

AWK:将行换行为 72 个字符
$ awk 'length > 72' {HOW TO PRINT THE LINEs IN PCS?} msg

即我希望它在 72 个字符后添加\n并继续,因此最初您可能需要删除所有 single\n并添加它们。使用其他工具可能会更容易,但让我们尝试一下 awk。

[更新]

威廉姆森提供了正确的答案,但需要一些帮助才能阅读它。我用下面的更简单的示例将问题分成几个部分。

  1. 为什么下面的代码\t在两种情况下都会打印,gsub应该替换什么? x 是一个虚拟文件,末尾有一些奇数 0。

  2. 攻击线line = $0 \n more = getline \n gsub("\t"," ")威廉姆森的回复line显然得到整个标准输出,同时more得到弹出值$0,对吧?

第 1 部分的代码

$ gawk '{ hallo="tjena\t tjena2"; gsub("\t"," "); }; END {print hallo; gsub("\t", ""); hallo=hallo gsub("\t",""); print hallo }' x
tjena  tjena2
tjena  tjena20

答案1

不使用 awk

我知道这可能只是您尝试使用 awk 解决的更大问题的一部分,awk或者只是尝试更好地理解 awk,但如果您真的只想将行长度保持在 72 列,那么有一个很多更好的工具。

fmt工具的设计特别考虑到了这一点:

fmt --width=72 filename

fmt也会努力在合理的地方换行,使输出更容易阅读。有关什么是“合理地点”的info更多详细信息,请参阅该页面。fmt

答案2

下面是一个 AWK 脚本,它对长行进行换行并重新换行剩余部分以及短行:

awk -v WIDTH=72 '
{
    gsub("\t"," ")
    $0 = line $0
    while (length <= WIDTH) {
        line = $0
        more = getline
        gsub("\t"," ")
        if (more)
            $0 = line " " $0
        else
            $0 = line
            break
    }
    while (length >= WIDTH) {
        print substr($0,1,WIDTH)
        $0 = substr($0,WIDTH+1)
    }
    line = $0 " "
}

END {
    print
}
'

CPAN 上有一个 Perl 脚本,它可以很好地重新格式化文本。它被称为帕拉吉个人文件)。为了进行连字符,您还需要TeX::Hyphen

SWITCHES
--------
The available switches are:

--width=n (or -w=n or -w n)
    Line width is n chars long

--left (or -l)
    Output is left-justified (default)

--right (or -r)
    Output is right-justified

--centered (or -c)
    Output is centered

--both (or -b)
    Output is both left- and right-justified

--indent=n (or -i=n or -i n)
    Leave n spaces for initial indention (defaults to 0)

--newline (or -n)
    Insert blank lines between paragraphs

--hyphenate (or -h)
    Hyphenate word that doesn't fit on a line

以下是我为支持左边距选项所做的一些更改的差异:

12c12
< my ($indent, $newline);
---
> my ($indent, $margin, $newline);
15a16
>   "margin:i" => \$margin,
21a23
> $margin = 0 if (!$margin);
149a152
>     print " " x $margin;
187a191,193
>   print "--margin=n (or -m=n or -m n)  Add a left margin of n ";
>   print "spaces\n";
>   print "                                (defaults to 0)\n";

答案3

Awk 是一种图灵完备的语言,而不是一种特别混乱的语言,因此截断行很容易。这是一个简单的命令式版本。

awk -v WIDTH=72 '
{
    while (length>WIDTH) {
        print substr($0,1,WIDTH);
        $0=substr($0,WIDTH+1);
    }
    print;
}
'

如果你想截断单词之间的行,你可以用 awk 进行编码,但识别单词并不是一件简单的事(因为更多的原因与自然语言有关,而不是算法难度)。许多系统都有一个名为的实用程序fmt可以做到这一点。

答案4

您询问为什么awk代码会发出制表符以及零从何而来。

  1. 该代码不会hello通过调用修改字符串gsub()。有两个参数,gsub()作用于$0。要实际修改hallo变量,请使用gsub(..., ..., hallo).

  2. 您在字符串末尾得到零,因为gsub()返回所做的替换数,并且在某一时刻您将此数字附加到 的值hallo

我知道至少有三个专门用于包装和格式化文本段落的实用程序:

  1. fold,“折叠线过滤器”,即标准 POSIX 实用程序。它只是插入换行符并且不重排文本。

  2. fmt,“简单文本格式化程序”,它也经常默认安装在 Unix 系统上,并且比重fold排段落更智能。

  3. par,”用于重新格式化段落的过滤器”,它具有检测段落前缀和后缀的附加功能(例如周围有 ASCII 框的文本,或一些源代码中的注释),并且处理缩进和悬挂缩进比fmt.

相关内容