AWK:行を72文字に折り返す


7
$ awk 'length > 72' {HOW TO PRINT THE LINEs IN PCS?} msg

つまり\n、72文字後に追加して続行したいので、最初にすべてのを削除し\nて追加する必要がある場合があります。他のツールを使う方が簡単かもしれませんが、試してみましょう。

[更新]

ウィリアムソンは正しい答えを提供しましたが、それを読むためにいくつかの助けが必要でした。以下の簡単な例で問題をいくつかの部分に分けます。

  1. 以下のコード\tが両方のケースで印刷されるのはなぜgsubですか?xはダミーファイルであり、最後に奇数の0があります。

  2. ウィリアムソンの返信のline = $0 \n more = getline \n gsub("\t"," ")を攻撃して、明らかに値がポップされている間、標準出力全体が表示されますよね?linemore$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

回答:


4

以下は、長い行をラップし、残りの行と短い行を再ラップする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スクリプトがあり、テキストを再フォーマットする非常に優れた仕事をします。これは、paradj個々のファイル)と呼ばれます。ハイフネーションを行うには、も必要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";

ちなみに、私はGillesのスクリプトを持ち上げて、私の一部として使用しました。
追って通知があるまで一時停止。

13

awkを使用しない

これは、あなたが解決しようとしているより大きな問題の一部であるawkか、単にawkをよりよく理解しようとする試みの一部である可能性があることを理解していますが、行の長さを72列に維持したい場合は、はるかに優れたツールがあります。

このfmtツールは、特にこれを念頭に置いて設計されました。

fmt --width=72 filename

fmtまた、適切な場所で改行して、出力を読みやすくします。「リーズナブルな場所」infoについての詳細は、こちらのページをご覧くださいfmt


GNU fmtはマルチバイトエンコーディングをサポートしておらずwidth、文字ではなくバイトを意味します。
Phillip Kovalev 2013年

4
macOSユーザーが使用できるfold -s -w 72
Edward Loveall

@EdwardLoveall foldはGNUシステムでも動作します(GNUに付属coreutils)。
heemayl 2017年

3

Awkはチューリング完全言語であり、特に難読化されていないため、行を切り捨てるのは簡単です。これは簡単な命令型バージョンです。

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

単語間の行を切り詰める場合は、awkでコードを記述できますが、単語の認識は簡単ではありません(アルゴリズムの難しさよりも自然言語に関係しているため)。多くのシステムには、fmtまさにそれを行うと呼ばれるユーティリティがあります。


えっと、私はあなたがあなたの文章を書いているときにこれを含めるために私の回答を編集していました。編集を削除するだけだと思います。他の誰かが答えを書いているときが見えたらいいのにと思います。
Steven D

1
厳密に言えば、スクリプトは行を切り捨てません。むしろ、それは長い行をラップしますが、残りを再ラップしません。
追って通知があるまで一時停止。

2

次に、スペースで分割するAwk関数を示します。

function wrap(text,   q, y, z) {
  while (text) {
    q = match(text, / |$/); y += q
    if (y > 72) {
      z = z RS; y = q - 1
    }
    else if (z) z = z FS
    z = z substr(text, 1, q - 1)
    text = substr(text, q + 1)
  }
  return z
}

驚いたことに、これはfoldまたはfmtよりもパフォーマンスが優れています。

ソース


2

あなたは、awkコードがタブを発行した理由とゼロがどこから来たかを尋ねました。

  1. コードは呼び出しでhello文字列を変更しませんgsub()。2つの引数を指定すると、にgsub()作用し$0ます。hallo変数を実際に変更するには、を使用しますgsub(..., ..., hallo)

  2. gsub()行われた置換の数を返すため、文字列の最後にゼロが表示され、ある時点でこの数をの値に追加しますhallo

テキストの段落の折り返しと書式設定を行うためのユーティリティが少なくとも3つあることは知っています。

  1. fold、「折り線のフィルタ」。これは標準のPOSIXユーティリティです。改行を挿入するだけで、テキストをリフローしません。

  2. fmt、「単純なテキストフォーマッタ」。これは、デフォルトでUnixシステムにインストールされることも多く、fold段落をリフローする場合よりもかなりスマートです。

  3. par、「段落を再フォーマットするためのフィルター」。段落のプレフィックスとサフィックス(ASCIIボックスが周囲にあるテキスト、または少しのソースコードのコメントなど)を検出する追加機能があり、インデントとぶら下げインデントをかなりよく処理します。よりfmt


0

gensubを使用すると、foldセマンティクスを取得するために、次のように実行できます。

awk '{printf gensub("(.{0,72})","\\1\n","g")}' 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.