プログラミング
逆引き
クライアントとの通信
VisMでの通信
Factoryでの通信
WebServiceでの通信
CSP (Cache' Server Pages)
Cache'SQL
設定・性能


【広告】









逆引きCache' Object Script

Cache' Object Script

文字列 数値 ファイル 日時 ユーティリティ

文字列

文字列の結合

_ (アンダースコア)記号で文字列を結合します。

> Set a="吾輩は", b="猫である"
> Set c=a_b         // aとbを結合
> Write c
吾輩は猫である

文字列の長さを取得

$Length(文字列)を使います。全角半角の区別なく、文字の数を返します。

昔で言う何バイト(半角文字1つを長さ1、全角文字1つを長さ2として計算する)を取得するには$ZWidthを使用します。

> Write $Length("あいうABC") // 文字数をカウント
6
> Write $ZWidth("あいうABC") // 全角文字は長さ2としてカウント
9

文字列に引用符"を入れる

文字列中に"を入れるには、"を2つ重ねます。

> Write "20゚25'00"""
20゚25'00"

文字列の一部分を取得

$Extractを使用します。取得開始位置を第2引数、取得終了位置を第三引数に渡します。先頭が1文字目になります。
> Write $Extract("ABCDE",3)
C
> Write $Extract("ABCDE",2,4)
BCD
> Write $Extract("ABCDE",3,99)  // 文字列長より大きい値を指定すると、末尾まで取得
CDE
末尾を取得するには、位置指定に * を使用すると便利です。
> Write $E("ABCDE",*)        // 末尾を取得
E
> Write $E("ABCDE",*-2,*)    // 末尾3文字を取得
CDE

区切り文字で区切られた部分文字列を取得

$Pieceを使用します。
なお、区切り文字でいくつに分割されているかは$Lengthの第2引数を指定することで取得できます。

> Write $Piece("12:34:56",":",3)   // :で区切られた、3ブロック目を取得
56

> Write $Piece("12:34:56",":",2,3) // :で区切られているとして、2番目から3番目を取得
34:56

> Write $Length("12:34:56",":")     // 文字列は:で何個に区切られるか
3

> Set x="12:34:56"
> For i=1:1:$Length(x,":") { Write $Piece(x,":",i),! }    //文字列xを:区切りで順番に取得
12
34
56

文字列中に指定文字列があることを確認

$Findまたは [ 演算子を使用します。
$Findは見つかった指定文字列が終了した次の文字の位置を返します。
 [ 演算子は、指定された文字列が含まれるかどうかだけを返します。

指定された文字列が含まれるかどうかの判定だけれあれば、 [ 演算子を使用する方が高速です。

> Write $F("ABCDE","CD")  // CDが見つかった次の文字
5

> Write "ABCDE"["CD"     // 見つかれば1(true)、見つからなければ0(false)
1

正規表現による確認

$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.Replace
First("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エスケープする
&lt;H1&gt;Test&lt;/H1&gt; 

文字コード関係

$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が一致するか確認
一致