Tips

長い文章を一定の文字数で改行する正規表現

日付2009/10/28
ID75893 (英語原文参照)
バージョン11
プラットフォームMac & Win

下記のように長い文章を一定の文字数で改行させることは、4D 2004以前ではなかなかたいへん"でした。


> Lorem ipsum dolor sit amet, risus aliquam sollicitudin pede egestas
> massa libero, cursus integer sed quis et molestie metus, nulla pede
> adipiscing sed orci, ac eu consectetuer et massa adipiscing, sed blandit
> ligula enim turpis rutrum imperdiet. Hendrerit quam tincidunt viverra
> lacus, sem dolor venenatis ultrices mauris, praesent egestas eleifend
> inceptos metus rutrum, nullam nec maecenas erat et fusce nibh, elit
> pellentesque sed amet et adipiscing. Lacus urna et nunc, odio ipsum,
> posuere viverra praesent voluptatum urna ut scelerisque, massa commodo
> velit. In dictumst at cras. Eget feugiat. Mollis inceptos convallis eros
> sapien, facilisis scelerisque mauris mauris orci magna. Dolor arcu
> temporibus, maecenas et porta arcu.


4D v11 SQLは、Match regexコマンドで正規表現が使用できるので、こうした処理が非常に簡単です。

はじめに、単語の途中で改行が入らないように、境界(ワードワウンダリー)でマッチする正規表現が必要です。次に、一行の最大文字数を超えないように、文字数の範囲を指定する必要があります。扱う文字がASCII(0-127)に限られていれば、次のような正規表現でじゅうぶんでしょう。

$Pat_T:="(?:[ -~]{1,72}(?:$|\\s))"

(?:regex) はノンキャプチャリングと呼ばれるパターンです。このパターンにマッチした文字列は、メモリにスタックされません。パターンが出現する位置だけが問われている場合、このような正規表現が使用されます。

"[ -~]"という正規表現は、32(スペース)から126(チルダ)まで、という意味です。次の"{1,72}"という正規表現は、最少で1、最多で72という文字数の出現回数を指定しています。最後の"(?:$|\\s)"という表現は、やはりノンキャプチャリングで、$(文字列の終末、キャレッジリターンあるいはラインフィード)または\s(ホワイトスペース文字)を意味します。いずれも基本の正規表現です。


基本の正規表現について


http://www.regular-expressions.info/reference.html

http://www.regular-expressions.info/refadv.html


しかしながら、このような正規表現では、フルセットのUnicodeに対応できているとはいえません。4DはUnicodeアプリケーションなので、次のような正規表現のほうが適切です。

$Pat_T:="(?:[^\\p{C}]{1,72})(?:$|\\p{Z})"

ノンキャプチャリングのグループを使用している点は一緒ですが、パターンが違っています。 "[^\\p{C}]"とは、未使用のコードポイントおよび制御文字のプロパティ(\p{C})ではない(^)という意味です。次の"{1,72}"は、文字数の範囲を指定しています。"(?:$|\\p{Z})"は、"(?:$|\\s)"に似ていますが、あらゆるホワイトスペース文字と非表示プロパティを包含しており、より包括的です。


Unicode版の正規表現およびUnicode文字のプロパティについて


http://www.regular-expressions.info/unicode.html#prop

http://www.regular-expressions.info/refunicode.html


正規表現を使用して改行を挿入するには次のようなコードを記述します。

$Start_L:=1
$FoundAt_L:=0
$Length_L:=0
$Bool_B:=Match regex($Pat_T;$Buf_T;$Start_L;$FoundAt_L;$Length_L)
While ($Bool_B)
    $Buf_T:=Insert string($Buf_T;"\r> ";$FoundAt_L)
    ` Plus 3 to account for the inserted characters
    $Start_L:=$FoundAt_L+$Length_L+3
    $Bool_B:=Match regex($Pat_T;$Buf_T;$Start_L;$FoundAt_L;$Length_L)
End while

正規表現を使用して配列に分解するには次のようなコードを記述します。

ARRAY TEXT($Fold_aT;0)
$Start_L:=1
$FoundAt_L:=0
$Length_L:=0
$Bool_B:=Match regex($Pat_T;$Buf_T;$Start_L;$FoundAt_L;$Length_L)
While ($Bool_B)
    APPEND TO ARRAY($Fold_aT;Substring($Buf_T;$FoundAt_L;$Length_L))
    $Start_L:=$FoundAt_L+$Length_L
    $Bool_B:=Match regex($Pat_T;$Buf_T;$Start_L;$FoundAt_L;$Length_L)
End while