Go to the first, previous, next, last section, table of contents.


テキスト操作用の組み込みマクロ

m4には部分文字列の抽出、検索、置換など様々な方法でテキストを 操作するための組み込みマクロがあります。

文字列の長さを計算する

文字列の長さはlenで計算できます。

len(string)

このマクロはstringの長さを表す10進数に展開されます。

len()
=>0
len(`abcdef')
=>6

組み込みマクロlenは引数が与えられたときだけ認識されます。

部分文字列で検索する

部分文字列の検索はindexで行います。

index(string, substring)

このマクロはstringの中でsubstringが最初に出現する 位置のインデックスに展開されます。 stringの先頭にある文字のインデックスは0です。 substringstringに含まれないとき、 index`-1'に展開されます。

index(`gnus, gnats, and armadillos', `nat')
=>7
index(`gnus, gnats, and armadillos', `dag')
=>-1

組み込みマクロindexは引数が与えられたときだけ認識されます。

正規表現で検索する

正規表現の検索は組み込みマクロregexpで行います。

regexp(string, regexp, opt replacement)

このマクロはregexpstringの中を検索します。 正規表現の構文はGNU Emacsのものと同じです。 See section `Syntax of Regular Expressions' in The GNU Emacs Manual.

replacementを省略すると、regexpstringの中で regexpに最初にマッチした部分のインデックスに展開されます。 regexpstringのどこにもマッチしない場合は-1に展開されます。

regexp(`GNUs not Unix', `\<[a-z]\w+')
=>5
regexp(`GNUs not Unix', `\<Q\w*')
=>-1

replacementを与えたときは、regexpはこの引数の値に展開されます。 このときreplacementに含まれる`\n'regexp中の n番目のカッコでくくられた部分式にマッチしたテキストに置き換えられ、 `\&'は正規表現全体にマッチしたテキストに置き換えられます。

regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***')
=>*** Unix *** nix ***

組み込みマクロregexpは引数が与えられたときだけ認識されます。

部分文字列を抽出する

部分文字列はsubstrを使って抽出します。

substr(string, from, opt length)

このマクロはstringのインデックスfromから始まるlength文字分 の部分文字列に展開されます。 lengthを省いたときはstringの最後までになります。 文字列の最初のインデックスは常に0です。

substr(`gnus, gnats, and armadillos', 6)
=>gnats, and armadillos
substr(`gnus, gnats, and armadillos', 6, 5)
=>gnats

組み込みマクロsubstrは引数が与えられたときだけ認識されます。

文字の置換

文字の置き換えはtranslitで行います。

translit(string, chars, replacement)

stringの各文字のうちcharsに出て来る文字をそれぞれ replacement中で同じ位置にある文字に置き換えたものに展開されます。

replacementcharsより短いときは 余分な文字は展開後のテキストから削除されます。 replacementを省略すると展開後のテキストは stringからcharsに含まれる文字すべてを削除したものになります。

charsreplacementのどちらにも文字範囲を含めることができます。 たとえば`a-z' (すべての小文字アルファベット)や `0-9' (すべての数字)などです。 charsreplacementにダッシュ`-'そのものを含めるときは 最初か最後に置いてください。

範囲の最後の文字が最初の文字より`小さい'場合もエラーではありません。 そういうケースでは範囲が逆に広がります。 つまり`9-0'は文字列`9876543210'を意味します。

translit(`GNUs not Unix', `A-Z')
=>s not nix
translit(`GNUs not Unix', `a-z', `A-Z')
=>GNUS NOT UNIX
translit(`GNUs not Unix', `A-Z', `z-a')
=>tmfs not fnix

最初の例は大文字のアルファベットをすべて削除します。 2番目の例は小文字を大文字に変換します。 3番目の例は大文字すべてを小文字に変換しながら`反射'させます。 最初の2つの例のほうがはるかに一般的です。

組み込みマクロtranslitは引数が与えられたときだけ認識されます。

正規表現でテキストの置換をする

文字列の全置換(global substitution)はpatsubstで行います。

patsubst(string, regexp, opt replacement)

string中でregexpにマッチする部分を探し、 それらをすべてreplacementに置換します。 正規表現の構文はGNU Emacsのものと同じです。

stringの中でregexpに適合するどの箇所にも含まれない部分は展開後の テキストにそのまま残ります。 マッチする箇所が見つかるたびに、 サーチはそのマッチした箇所の終りから続行されます。 したがってstring内のある文字が2回置換されることは決してありません。 regexpが長さ0の文字列にマッチしたときは、 無限ループを避けるためサーチの開始位置は1文字前に進められます。

置き換えが行われるときは、replacementに含まれる`\n'regexp内のカッコでくくられたn番目の部分式にマッチしたテキスト に置き換え、`\&'を正規表現全体にマッチしたテキストに置き換えたものが 展開後のテキストに挿入されます。

引数replacementは省略することができます。 そのときはregexpにマッチしたテキストは削除されます。

patsubst(`GNUs not Unix', `^', `OBS: ')
=>OBS: GNUs not Unix
patsubst(`GNUs not Unix', `\<', `OBS: ')
=>OBS: GNUs OBS: not OBS: Unix
patsubst(`GNUs not Unix', `\w*', `(\&)')
=>(GNUs)() (not)() (Unix)
patsubst(`GNUs not Unix', `\w+', `(\&)')
=>(GNUs) (not) (Unix)
patsubst(`GNUs not Unix', `[A-Z][a-z]+')
=>GN not 

次はもうすこし現実的な例です。 文字列の中にマクロupcasedowncaseの呼び出しを挿入することで、 単独の単語または文全体をキャピタライズ(capitalize)します。

define(`upcase', `translit(`$*', `a-z', `A-Z')')dnl
define(`downcase', `translit(`$*', `A-Z', `a-z')')dnl
define(`capitalize1',
     `regexp(`$1', `^\(\w\)\(\w*\)', `upcase(`\1')`'downcase(`\2')')')dnl
define(`capitalize',
     `patsubst(`$1', `\w+', `capitalize1(`\&')')')dnl
capitalize(`GNUs not Unix')
=>Gnus Not Unix

組み込みマクロpatsubstは引数が与えられたときだけ認識されます。

書式付き出力

書式付き出力はformatを使って行うことができます。

format(format-string, ...)

このマクロはC言語の関数printfとよく似た動作をします。 最初の引数は書式指定文字列で`%'指定を含めることができます。 formatは展開されると書式付の文字列になります。

2, 3の例を使って説明するのが一番でしょう。

define(`foo', `The brown fox jumped over the lazy dog')
=>
format(`The string "%s" is %d characters long', foo, len(foo))
=>The string "The brown fox jumped over the lazy dog" is 38 characters long

See section ループと再帰で定義されているforloopマクロを使って 表形式の出力をするときはformatを次のように使うことができます。

forloop(`i', 1, 10, `format(`%6d squared is %10d
', i, eval(i**2))')
=>     1 squared is	    1
=>     2 squared is	    4
=>     3 squared is	    9
=>     4 squared is	   16
=>     5 squared is	   25
=>     6 squared is	   36
=>     7 squared is	   49
=>     8 squared is	   64
=>     9 squared is	   81
=>    10 squared is	  100

組み込みマクロformatはANSI Cの`printf'関数をモデルとしており、 次の標準的な`%'指定をサポートしています: `c', `s', `d', `o', `x', `X', `u', `e', `E', `f'。 またフィールド幅と精度指定、モディファイア `+', `-', ` ', `0', `#', `h', `l'をサポートしています。 printfの動作について更に詳しいことは C ライブラリ・マニュアルを見てください。


Go to the first, previous, next, last section, table of contents.