$Locate関数を使用します。該当するパターンの見つかった先頭の位置を返します。
この関数は2012.2以降で使用できます。
> Write $Locate("123-456789","\d{4}")
//4桁の数値が見つかる場所を返す
5
> Write $Locate("123-456789", "\d{4}",
, , x)
//第5引数xに見つかった文字列が格納される
5
> Write x
//見つかった文字列を表示
4567
文字置換
文字列の置換には、次の3つの方法があります。
- 通常の文字列置換を行う$Replace関数
- 1文字単位の置換を行う$Translate関数
- 正規表現による置換を行う方法
通常の文字列置換を行う$Replace関数
文字列の置換には、$REPLACE関数を使用します。
> Write $REPLACE("This is a pen.","pen","book") // penをbookに置き換え
This is a book.
> Write $REPLACE("This is a pen","is","") // isを除去
Th a pen.
1文字単位の置換を行う$Translate関数
$TRanslate関数を使用します。文字列の置き換えではなく1文字単位の置き換えであることに注意してください。
> Write $TR("ABCDE","BD","bd") // Bをbに、Dをdに置き換え
AbCde
> Write $TR("A-B:CD)E",":-)") // 文字列中の:と-と)を、ヌルに置き換える。つまり:と-と)を除去する
ABCDE
> Write $TR("abcd年ef月gh日","abcdefgh",$ZD($H,8)) //こんな使い方もできます
2012年03月07日
正規表現による置換を行う方法
2012.2以降で使用できるようになった正規表現による置換の方法です。
Set rgx=##class(%Regex.Matcher).%New("\d{3,}","123-45-6789")
Write rgx.ReplaceAll("xxx")
/// 123-45-6789の3桁以上の数値を全てxxxに置換
→ xxx-45-xxx
Set rgx=##class(%Regex.Matcher).%New("\d{3,}","123-45-6789")
Write rgx.ReplaceFirst("xxx")
/// 123-45-6789の3桁以上の数値の最初のものについてxxxに置換
→
xxx-45-6789
トリミング
$ZSTRIP関数を使用します。
第一引数がトリミングされる文字列
第二引数がトリミングの方法です。 < が前方トリミング、 > が後方トリミング、<>
で前後方トリミングです。
第三引数がトリミングする文字列です。
> Write $ZSTRIP("---ABCDE---", "<", "-") // 文字列前方の-を除去
ABCDE---
> Write $ZSTRIP("---ABCDE---", ">", "-") // 文字列後方の-を除去
---ABCDE
> Write $ZSTRIP("---ABCDE---", "<>", "-") // 文字列前方後方の-を除去
ABCDE
|
第2引数には、マスクコードというよく使われる除去パターンを指定することができます。特に
Wはよく使うので覚えておきましょう。
- W … 空白(タブ・半角スペース) 全角スペースは含まれないので、必要な場合は第3引数に指定する。
- P … 空白と半角区切り文字(:;,./など)
- C … 制御文字(文字コード0〜31、127〜159)
> Write $ZSTRIP(" ABCDE ", "<>W") // 文字列前後方の空白を除去
ABCDE
> Write $ZSTRIP(",AB,CD,E, // ", "<>WP", "-") // 文字列前後方の空白・区切り文字・ハイフンを除去
AB,CD,E
|
パターンマッチ
パターンマッチは大きく分けて2つの方法があります。正規表現 と ?演算子です。
正規表現によるパターンマッチ
バージョン2012.2以降で正規表現が使えるようになり、パターンマッチは
$Match関数で行えるようになりました。
> Write $Match(1234567, "\d{7}")
// 第一引数が、7桁の数値かどうか確認。
1
> if
'$Match(zipcode,"\d{3}-\d{4}")
{ Write "郵便番号として正しい形式ではありません" } // 数値3桁 +
ハイフン + 数値4桁でなければ、メッセージを表示
注意が必要なのが、$Matchは第一引数の文字列全体とマッチするかどうか判定する点です。(第二引数に自動的に^と$が付与されるイメージです) 部分一致の場合は
$Locate関数を使用します。
? 演算子によるパターンマッチ
パターンの指定は独特の方法ですので
マニュアルを参照して下さい。パターンは必ず繰り返し回数とパターン文字を組み合わせて書きます。
パターン文字
N |
半角数値 |
A |
半角アルファベット(大文字・小文字の両方) |
P |
半角記号 |
ZFWCHARZ |
全角文字 |
ZHWKATAZ |
半角カタカナ |
> if "123" ? 3N { Write "3桁の数字です" } // "123"が3桁の数値(3N)かどうか判定
3桁の数字です
> if "123" ? 1.N { Write "1桁以上の数値です" }
1桁以上の数値です
> if "123" ? 4.10N { Write "4桁以上10桁以内の数値です"} // 該当しない
> if "090-1234-4321" ? 3N1"-"4N1"-"4N { Write "NNN-NNNN-NNNNの形式" }
// 3桁数値 + 1つのハイフン + 4桁数値 + 1つのハイフン + 4桁数値
NNN-NNNN-NNNNの形式
> if addr ? 1.an.50(.1"-".1"_".1".".1a.1n)1"@"1.an1.(1"."1.an) {
Write "メールアドレスの形式" }
> if "C" ? 1(1"A",1"B") Write "AまたはB" // OR条件は( , ) で書く
|
(古い方法) 2012.2以前での正規表現でのパターンマッチ
Windows環境の場合はActivateでMicrosoft VBScript Regular Expressions を使用することで正規表現を使用したパターンマッチができるようです。
(以下ではパッケージ Activate でクラスを生成しています)
USER>s r=##class(Activate.VBScriptuRegExpu55.RegExp).%New()
USER>s r.Global=1
USER>s r.Pattern="^[a-zA-Z]{1,3}$"
USER>w r.Test("abc")
-1
USER>w r.Test("aBc")
-1
USER>w r.Test("abcd")
0
USER>w r.Test("a1c")
0
USER>s r=""
|
以下のサイトでは、Perl正規表現ライブラリを使用する方法が説明されています。この方法ならばLinuxでも使用出来るようです。
http://cache.gklein.org/regex/
小文字・大文字を変換する
$ZCONVERT関数を使用します
> Write $ZCONVERT("abcdEFG","U") //大文字化
ABCDEFG
> Write $ZCONVERT("abcdEFG","L") //小文字化
abcdefg
> Write $ZCONVERT("I AM A CAT. no name yet.","W") //単語の先頭文字だけ大文字化
I Am A Cat. No Name Yet.
> Write $ZCONVERT("I AM A CAT. no name yet.","S") //文の先頭文字だけ大文字化
I am a cat. No name yet.
|
文字列の全角化
$ZZENKAKU関数を使用します
> Write $ZZENKAKU("123-=abCD")
123−=abCD
> Write $ZZENKAKU($ZCVT("123-=abCD","U")) //$ZCVTで大文字化してから、全角化
123−=ABCD
|
文字列の右詰め、左詰め
文字列を右詰にするには
$Justify関数を使用します。第2引数で指定した文字長にするために必要なスペースを、第一引数の前方に追加します。
> Write $J("123", 5) // 5文字分の幅で右詰にするため、先頭に2つスペースが入る
123
> Write $TR( $J("123", 5), " ", "0") // 5文字分の幅で右詰にするため、先頭に2つゼロが入る
00123
> Write $J(100, 10, 2) // 100に小数点以下2ケタを付けて、10文字にするため必要なスペース(4つ)が入る
100.00
|
左詰めにするには、$Lenghtで長さを求めて、必要な量のスペースを後ろにつける必要があります。
> Set x="ABC"
> Write x For i=1: 1: 10-$L(x) {
Write " " } Write "DE" // ABC
と出力した後、10-3 = 7個スペースを出力し、DEと出力
ABC
DE
> Write x, $J("", 10-$L(x)), "DE" //
$Jを使って、xの長さに応じたスペースを出力する方法
ABC DE
> Write x,?10,"DE" // ?で横位置指定することもできます
ABC DE
指定バイト数に格納できるかを確認する
$ZPosition関数を使用します。
第2引数で指定した半角文字数(全角1文字を2バイト換算)の表示スペースに、何文字目まで表示できるかを返します。
ターミナルで動作するプログラムを作るときは、よく使いました。
> Write $ZPosition("のぞみ17号",8) // 半角8文字分のスペースに"のぞみ17号"を
// 表示するなら、何文字目まで表示できるか
5 // 5文字目まで
> Write $ZPosition("のぞみ17号",9) // 半角9文字分のスペースに"のぞみ17号"を
// 表示するなら、何文字目まで表示できるか
5.5 // 5文字目までしか表示できない
|
文字列エンコードを変換する。文字列をエスケープする。
$ZCONVERT関数を使用します。
第一引数が変換したい文字列、第二引数が変換の方向、第三引数に変換パターンを指定します。
第二引数は、I または
O が指定できます。
I のとき、
第一引数の文字列は
第三引数の形式でエンコードされているものとして、変換を実行します。
O のとき、
第一引数の文字列を
第三引数の形式でエンコードするものとして、変換を実行します。
第三引数の変換パターンとしては、以下のものが指定できます。
SJIS, EUC, UTF8 等のロケールに定義されているエンコード
HTML, JS, URL, XML
> Write $ZCVT("あいう","O","EUC") // EUCで変換したら文字化けする
?????? // ←EUC文字コードで出力されている。ターミナルの
// 文字コード設定と一致していないため表示できない
> Write $ZCVT( $ZCVT("あいう","O","EUC") ,"I","EUC")
// EUCで変換した「あいう」を、EUCとして取り込むと元の文字列が得られる
あいう
> Write $ZCVT("<H1>Test</H1>", "O", "HTML") // 文字列をHTMLエスケープする
<H1>Test</H1>
|
文字コード関係
$Char関数, $Ascii関数 を使用します。
> Write $Ascii("A") // Aのアスキーコードを返す
65
> Write $Char(65) // アスキーコード65の文字を返す
A
|
文字列のハッシュ値を取得
$SYSTEM.Encryption (実体は
%System.Encryptionクラス)
を使用して、ハッシュ値を取得します。
> Write $SYSTEM.Encryption.MD5Hash("あいうえお") // MD5ハッシュ
|qÃ2ÔØ7ì°~¾ÚX // バイト列なので文字化けしています
> Write $SYSTEM.Encryption.SHA1Hash("あいうえお") // SHA-1ハッシュ
¼+ÜVX_~öo ~;üüÓ* // バイト列なので文字化けしています
// バイト列の中身をZZDUMPコマンドを使って確認してみます
> ZZDUMP $SYSTEM.Encryption.SHA1Hash("あいうえお")
0000: BC 2B DC 1B 33 56 15 58 5F 7E F6 6F 09 04 7E 3B ¼+Ü.3V.X_~öo..~;
0010: FC FC D3 2A üüÓ*
// バイト列の中身を16進文字列に変換します
> Set bs = $SYSTEM.Encryption.SHA1Hash("あいうえお")
> Set hexStr="" F i=1:1:$L(bs) S hexStr=hexStr_$TR($J($ZHEX($A($E(bs,i))),2)," ",0)
> Write hexStr
BC2BDC1B335615585F7EF66F947E3BFCFCD32A //ZZDUMPの結果と同じ
文字列の圧縮
$system.Util.Compress() 、 $system.Util.Decompress() メソッドを使用します。
> Set a="" For i=1:1:10000 { Set a=a_"0" } // 変数aに0が1万個連なった文字列を格納
> Write $Length(a)
10000
> Set b=$system.Util.Compress(a) // 変数aを圧縮し、変数bへ
> Write $Length(b)
20
> Set c=$system.Util.Decompress(b) // 変数bを解凍し、変数cへ
> If a=c { Write "一致" } // 圧縮前の変数aと、圧縮・解凍後の変数cが一致するか確認
一致