SAS言語の文字関連関数ANY◯◯◯◯について調べる


SASプログラミング言語を構成する要素であるSAS関数（カテゴリ別のSAS関数とCALLルーチン）のうち、文字の判別を行う冒頭に「ANY」がつくものについてまとめました。

公式マニュアル：SAS®9.4関数とCALLルーチン:リファレンス(第4版)

<br><br>

各関数の備考にてI18N（internationalization：国際化対応）のレベルが言及されています。どちらのレベルに準拠しているかを表に記載しておきました。
- I18Nレベル1：英語以外の言語を使用する場合、可能な限りI18Nレベル1の関数の使用は避けてください。特定の環境下では、I18Nレベル1の関数は、2バイト文字セット(DBCS)または複数バイト文字セット(MBCS)エンコーディングを使用すると正常に動作しない場合があります。
- I18Nレベル2：SBCS、DBCSおよびMBCS(UTF8)での使用目的で設計されています。


| 関数名 | 説明 | I18Nレベル |
|:-----------|:------------|:------------|
| ANYALNUM関数 | 文字列から英数字を検索し、最初に検索された文字の位置を返します。 | I18Nレベル1 |
| ANYALPHA関数 | 文字列から英字を検索し、最初に検索された文字の位置を返します。 | I18Nレベル1 |
| ANYCNTRL関数 | 文字列からコントロール文字を検索し、最初に検索された文字の位置を返します。 | I18Nレベル2 |
| ANYDIGIT関数 | 文字列から数字を検索し、最初に検索された数字の位置を返します。 | I18Nレベル2 |
| ANYFIRST関数 | VALIDVARNAME=V7のSAS変数名の開始文字として有効な文字を文字列から検索し、最初に検索された文字の位置を返します。 | I18Nレベル2 |
| ANYGRAPH関数 | 文字列からグラフィカル文字を検索し、最初に検索された文字の位置を返します。 | I18Nレベル1 |
| ANYLOWER関数 | 文字列から小文字を検索し、最初に検索された文字の位置を返します。 | I18Nレベル1 |
| ANYNAME関数 | VALIDVARNAME=V7のSAS変数名として有効な文字を文字列から検索し、最初に検索された文字の位置を返します。 | I18Nレベル2 |
| ANYPRINT関数 | 文字列から印刷可能な文字を検索し、最初に検索された文字の位置を返します。 | I18Nレベル1 |
| ANYPUNCT関数 | 文字列から句読文字を検索し、最初に検索された文字の位置を返します。 | I18Nレベル |2<br>z/OS環境のみで使用可能
| ANYSPACE関数 | 文字列から空白文字(空白、水平タブ、垂直タブ、キャリッジリターン、ラインフィード、フォームフィード)を検索し、最初に検索された文字の位置を返します。 | I18Nレベル2 |
| ANYUPPER関数 | 文字列から大文字を検索し、最初に検索された文字の位置を返します。 | I18Nレベル1 |
| ANYXDIGIT関数 | 数字を表す16進法の文字を文字列から検索し、最初に検索された文字の位置を返します。 | I18Nレベル1 |

<br><br>

一部だけ抜粋して挙動を確認します。

**ANYALNUM関数**
第二引数（start）の負の値の取り扱いが直感的でないため気をつけましょう。

```sas
data _null_;
    string='Next = Last + 1;';
    j=anyalnum(string, 1);
	put j;
run;
```
出力結果：1

第二引数（start）は、対象文字列のどこから検索するかを示しています。1であれば先頭からの検索です。文字列「Next = Last + 1;」の「N」が英数字に該当するため、先頭から数えて「N」のある位置の数字が返却されます。したがって結果は1となります。


```sas
data _null_;
    string='__Next = Last + 1;';
    j=anyalnum(string, 1);
	put j;
run;
```
出力結果：3

文字列「__Next = Last + 1;」の「N」が英数字に該当するため、先頭から数えて「N」のある位置の数字が返却されます。したがって結果は3となります。


```sas
data _null_;
    string='__Next = Last + 1;';
    j=anyalnum(string, 5);
	put j;
run;
```
出力結果：5

第二引数（start）が5であるため先頭から数えて5つ目の文字から検索を始めます。5つ目の文字「x」は英数字であり、結果は5となります。


```sas
data _null_;
    string='Next = Last + 1;';
    j=anyalnum(string, 0);
	put j;
run;
```
出力結果：0

第二引数（start）の値が0のときには必ず0が戻る仕様です。


```sas
data _null_;
    string='_____;____';
    j=anyalnum(string, 0);
	put j;
run;
```
出力結果：0

指定した文字列に英数字が見つからなかった場合には0を戻します。


```sas
data _null_;
    string='__Next = Last + 1;';
    j=anyalnum(string, -5);
	put j;
run;
```
出力結果：5

第二引数（start）の値が負である場合には右から左に文字列を検索します。startの絶対値自体は先頭から数えた文字の位置であるため、上記の例で言えば「__Nex」の「x」から右から左へ検索します。検索結果は先頭から数えた文字数の5となります。
 
```sas
data _null_;
    string='__Next = Last + 1__;';
    j=anyalnum(string, -50);
	put j;
run;
```
出力結果：17

第二引数（start）の値が負である場合には右から左に文字列を検索します。startの絶対値自体は先頭から数えた文字の位置であり、文字列よりも大きい場合には末尾からの検索となります。検索結果は「1」を先頭から数えた文字数の17となります。


<br><br>
**ANYCNTRL関数**

制御文字を検索します。
```sas
data _null_;
	/* CとDの間に制御文字「DC3」が入っている（※このエディタ上では表現できない） */
    string='ABCDEF';
    j=anycntrl(string, 1);
	put j;
run;
```
出力結果：4

第二引数（start）の仕様はANYALNUM関数 と同じです。

<br><br>
**ANYFIRST関数**

VALIDVARNAME=V7 の命名規則に沿う文字で、変数名の冒頭に付与できる文字を検索します。すなわちアルファベット（A-Zまたはa-z）またはアンダースコア（_）です。
```sas
data _null_;
    string='あいう甲乙丙ABC';
    j=anyfirst(string, 1);
	put j;
run;
```
出力結果：13

第二引数（start）の仕様はANYALNUM関数 と同じです。I18Nレベル2に準拠しているためマルチバイト文字が使用できますが、UTF-8の2バイト文字では1文字が2とカウントされるようです。


<br><br>

## SAS言語の実行環境

SAS言語の動作環境は[Altair SLC 及び Altair Analytics Workbench](https://www.brainpad.co.jp/services/products/Altair.html)を使用しております。詳細や最新情報は[Altair公式サイト](https://www.altairjp.co.jp/altair-analytics-workbench/)をご覧ください。

## 動作確認を行なった環境
- MacBookPro（2020 M1）
    - RAM 16GB
    - macOS Sonoma 14.4.1
- Altair SLC 2024 (05.24.03.00.001528)
- Altair Analytics Workbench 5.24.3.0.1528-GA-release-2024.2