(最終更新月:2023年4月)
✔当記事はこのような方に向けて書かれています
「GASで正規表現を書く方法について知りたい」
「そもそも正規表現の基本は?」
「GASで書く正規表現の実例が見せてほしい」
✔当記事の主な内容は以下のとおり
- 正規表現とは?GASの正規表現とは?
- 正規表現の基本的な用語とGASでの書き方
- GASで書く正規表現の実例集
当記事では、GASの正規表現についての基本はもちろん、さまざまな場面での具体的な使用例など、初心者にもわかりやすいよう解説しています。
ぜひ最後までご覧ください。
GASで正規表現を扱うための基礎知識
GASで正規表現を扱うための基本をご紹介します。
まずは一度目を通し、正規表現などについて理解をしておくことが大切です。
- 正規表現とは?
- Google Apps Script (GAS) での正規表現の利用
正規表現とは?
正規表現は、文字列のパターンを表現する強力なツール。
検索、置換、抽出などの操作を効率的におこなえます。
特定のパターンに一致する文字列を簡単に特定できるため、プログラミングやテキスト処理で非常に便利です。
例えば、「\d{3}-\d{4}」という正規表現は、日本の郵便番号の形式(123-4567)に一致します。
function findJapanesePostalCode() {
var text = "Sample text with a Japanese postal code: 123-4567.";
var regex = /\d{3}-\d{4}/g;
// 文字列と正規表現のマッチング
var matches = text.match(regex);
Logger.log(matches); // ['123-4567']
}
Google Apps Script (GAS) での正規表現の利用
Google Apps Script (GAS) は、Googleの各種サービスを拡張するためのJavaScriptベースのプログラミング言語です。
GASでは、正規表現を使用して、テキスト処理やデータ整形を効率的に行うことができます。
ドキュメントやスプレッドシートなど、さまざまなアプリと連携し、正規表現を使って効率よく作業が進められるのです。
正規表現の基本概念
正規表現の基本概念をご紹介します。
使用する言語に関わらず知っておくと必ず役に立つでしょう。
- メタ文字
- 文字クラス
- 量指定子
- グループ化
- 代替(OR)
- バックリファレンス
- 前方/後方アサーション(ルックアヘッド/ルックビハインド)
メタ文字
メタ文字は、正規表現の特殊文字で、特定の意味や機能を持っています。
メタ文字は以下のようなものです。
- .(任意の1文字)
- ^(行の先頭)
- $(行の末尾)
- *(直前の文字が0回以上の繰り返し)
- +(直前の文字が1回以上の繰り返し)
- ?(直前の文字が0回または1回の繰り返し)
- {}(繰り返しの回数を指定)
- [](文字クラスの定義)
- ()(グループ化)
- |(代替)
- \(エスケープ)
文字クラス
文字クラスは、特定の文字の集合を表し、角括弧[]内に文字を列挙することで定義できます。
例えば、[abc]は、a、b、cのいずれかの文字に一致します。
ハイフン(-)を使用して範囲を指定することもでき、[a-z]は小文字のアルファベット全てに一致します。
量指定子
量指定子は、繰り返しの回数を指定するために使用されます。
例えば、a*は、aが0回以上繰り返されるパターンに一致。
ほかにも以下のようなものがあります。
- +(1回以上の繰り返し)
- ?(0回または1回の繰り返し)
- {n}(n回の繰り返し)
- {n,m}(n回からm回の繰り返し)
グループ化
グループ化は、丸括弧(())を使用して、正規表現の一部をグループとして扱えます。
量指定子や代替演算子をグループ全体に適用できます。
例えば、「(abc)+」は、「abc」が1回以上繰り返されるパターンに一致。
また、グループ化は、マッチした部分文字列の抽出やバックリファレンスにも利用できるのです。
代替(OR)
代替(OR)は、「|」演算子を使用して、複数のパターンのいずれかに一致する条件を表現できます。
例えば、cat|dogは、「cat」または「dog」のいずれかの文字列に一致することを意図します。
複数の代替パターンをグループ化することで、より複雑な条件を表現することができるのです。
複数の例として、(apple|orange|banana)は、「apple」、「orange」、または「banana」のいずれかの文字列に一致します。
バックリファレンス
バックリファレンスは、正規表現内で以前にマッチしたグループを再利用する機能。
\nという形式で表現され、nはグループの番号を示します。
例として、2つの連続した同じ数字を見つける正規表現を考えると、「(\d)\1」となります。
- (\d):1つ目のグループで、任意の数字にマッチ
- \1:バックリファレンスとしてそのグループの参照を行い、同じ数字が再び現れる場合にマッチ
バックリファレンスを使えば、繰り返しパターンや特定のマッチング結果を効果的に表現できるのです。
前方/後方アサーション(ルックアヘッド/ルックビハインド)
前方/広報アサーションとは以下のとおり。
- 前方アサーション(ルックアヘッド):先読みをおこない、一致が成功するかどうかを確認
- 後方アサーション(ルックビハインド):現在の位置より前の文字列をチェック
それぞれ肯定的なものと否定的なものが存在します。
例えば、q(?=u)は、「q」の後に「u」が続く場合に一致しますが、「u」自体は含まれません。
GASでの正規表現の実装方法
GASでの実装方法・手順を見ていきましょう。
- 正規表現オブジェクトの作成
- 文字列とのマッチング
- 置換と分割
それぞれのステップがわかりやすいよう、パートごとにコードをご紹介していきます。
正規表現オブジェクトの作成
GASで正規表現を使用するには、まず正規表現オブジェクトを作成します。
例えば、var regex = new RegExp(“pattern”, “flags”);のようにして正規表現オブジェクトを作成できます。
function createRegexObject() {
// 正規表現オブジェクトを作成する(日本の電話番号のパターン)
var regex = new RegExp('\\d{2,4}-\\d{2,4}-\\d{4}', 'g');
return regex;
}
文字列とのマッチング
exec()やtest()メソッドを使って、文字列と正規表現が一致するかどうかを確認できます。
例えば、regex.test(string)は、正規表現が文字列に一致する場合はtrueを、そうでない場合はfalseを返します。
function findJapanesePhoneNumber() {
var text = "お問合せの際は次までご連絡ください。会社:03-1234-5678、携帯電話:090-1234-5678。";
var regex = createRegexObject();
// 文字列と正規表現のマッチング
var matches = text.match(regex);
Logger.log(matches); // ['03-1234-5678', '090-1234-5678']
}
置換と分割
replace()やsplit()メソッドを使って、正規表現に基づいた文字列の置換や分割ができます。
例えば、string.replace(regex, replacement)は、文字列内の正規表現に一致する部分を別の文字列に置換します。
function replaceAndSplitJapanesePhoneNumbers() {
var text = "お問合せの際は次までご連絡ください。会社:03-1234-5678、携帯電話:090-1234-5678。";
var regex = createRegexObject();
// 文字列内の電話番号を置換
var replacedText = text.replace(regex, "{電話番号}");
Logger.log(replacedText); // 'お問合せの際は次までご連絡ください。会社:{電話番号}、携帯電話:{電話番号}。'
// 電話番号をハイフンで分割
var matches = text.match(regex);
var splitPhoneNumbers = matches.map(function(phoneNumber) {
return phoneNumber.split('-');
});
Logger.log(splitPhoneNumbers); // [['03', '1234', '5678'], ['090', '1234', '5678']]
}
GASでの正規表現の応用例
GASでの正規表現の応用例を場面ごとに見ていきます。
このままコードを使って、時間短縮を図ってください。
- メールアドレスの検証
- 文字列から電話番号を抽出
- URLのパラメータ抽出
- 文字列の検索と置換
- テキストデータの整形
- スプレッドシートのデータ操作
メールアドレスの検証
正規表現を使って、メールアドレスが正しい形式になっているかどうかを検証できます。
例えば、「/^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,}$/」のような正規表現を使用します。
function isValidEmail(email) {
var regex = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)*\.[a-zA-Z]{2,}$/;
return regex.test(email);
}
var email = "example@example.com";
Logger.log(isValidEmail(email)); // true
文字列から電話番号を抽出
電話番号のパターンに一致する正規表現を使って、テキストから電話番号を抽出できます。
例えば、/(\d{2,4}-\d{2,4}-\d{4})/は、日本の電話番号のパターンに一致します。
function extractPhoneNumbers(text) {
var regex = /(\d{2,4}-\d{2,4}-\d{4})/;
return text.match(regex);
}
var text = "Call me at 03-1234-0000 or 080-1234-5679.";
Logger.log(extractPhoneNumbers(text)); // ['03-1234-0000', ‘080-1234-5679’]
URLのパラメータ抽出
URLからパラメータを抽出するために、正規表現を使用できます。
例えば、/[\?&]([^=]+)=([^&]*)/gという正規表現を使って、URL内のすべてのパラメータ名とその値を抽出することができます。
function extractUrlParameters(url) {
var regex = /[?&]([^=]+)=([^&]+)/g;
var params = {};
var match;
while ((match = regex.exec(url)) !== null) {
params[match[1]] = match[2];
}
return params;
}
var url = "https://example.com?page=1&category=books&lang=ja";
Logger.log(extractUrlParameters(url)); // {page: '1', category: 'books', lang: 'ja'}
文字列の検索と置換
正規表現を用いて、特定のパターンに一致する文字列を検索したり、置換したりすることができます。
例えば、特定の単語を強調表示するタグで囲む場合や、特定のパターンを削除する場合などに利用できます。
function replaceText(text, search, replace) {
var regex = new RegExp(search, 'g');
return text.replace(regex, replace);
}
var text = "I have a cat, a dog, and a bird.";
Logger.log(replaceText(text, "a ", "an ")); // "I have an cat, an dog, and an bird."
テキストデータの整形
正規表現を使って、テキストデータの整形を行うことができます。
例えば、改行や空白文字を削除したり、特定の文字列を一定の形式に変換したりすることが可能です。
function formatText(text) {
var regex = /[\n\s]+/g;
return text.replace(regex, " ").trim();
}
var text = " This is an\nexample of\n a messy text. ";
Logger.log(formatText(text)); // "This is an example of a messy text."
スプレッドシートのデータ操作
GASを使用して、Googleスプレッドシート内のデータを操作する際にも、正規表現が役立ちます。
例えば、セル内の特定の文字列を検索して置換する処理などが行えます。
function processSpreadsheetData() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var regex = /\d{3}-\d{2}-\d{4}/g;
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].length; j++) {
if (typeof data[i][j] === 'string' && regex.test(data[i][j])) {
sheet.getRange(i + 1, j + 1).setBackground("yellow");
}
}
}
}
正規表現のデバッグとテスト
正規表現のデバッグとテストをおこなう方法を見ていきましょう。
一般的なやり方とGASにおける方法をそれぞれご紹介します。
- オンラインツールの利用
- GASにおけるデバッグ方法
オンラインツールの利用
正規表現をデバッグやテストする際には、オンラインツール(例:Regex101)が便利です。
これらのツールを使うことで、正規表現の動作をリアルタイムで確認しながら、正確なパターンを作成することができます。
以下に、Regex101の使用方法を簡単に説明します。
- Regex101にアクセス
- 正規表現を入力:画面上部にある「Regular Expression」に、正規表現を入力
- 文字列を入力 :「Test String」の欄に、正規表現をテストするためのサンプル文字列を入力
- フレーバーを選択:画面上部のドロップダウンメニューから、使用したいプログラミング言語に対応する正規表現のフレーバー(バリエーション)を選択(Google Apps Scriptの場合は、「JavaScript」)
- 正規表現のマッチ結果を確認:マッチする場合、画面下部の「Match Information」欄にマッチした部分やグループ情報が表示、マッチしない場合、その旨が表示
- 説明とコード生成を活用:画面右側の「Explanation」欄では、入力した正規表現の各要素の説明が表示され、「Code Generator」タブをクリックすると、選択したフレーバーに対応するコードが生成される
GASにおけるデバッグ方法
GASで正規表現をデバッグする際には、Logger.log()関数を使用して、マッチング結果や置換結果をログに出力することができます。
これにより、スクリプトの実行結果を確認しながら、正規表現を修正していくことが可能です。
Logger.logを設定して実行したいときは、上部にある再生マークをクリックしましょう。
より高度な正規表現テクニック
より正規表現を極めるための高度なテクニックをご紹介します。
よく使われる方は知っておくべきだといえるでしょう。
- 演算子の優先順位
- ネストされたグループ
- オプションフラグ
演算子の優先順位
正規表現では、演算子の優先順位があります。
主なものは以下のとおり。
優先順位 | 演算子 | 説明 | 例 |
---|---|---|---|
1 | \ | エスケープ | \d は数字 |
2 | () | グループ化 | (abc) |
3 | [] | 文字クラス | [a-z] |
4 | *, +, ?, {} | 量指定子 | a* |
5 | ^, $ | 文字列の先頭・末尾 | ^abc, abc$ |
6 | | | 代替(OR) | cat|dog |
例としてはこちらをご覧ください。
- エスケープ:
\d{3}
は、3桁の数字にマッチします。 - グループ化:
(abc){2}
は、abcabc
にマッチします。 - 文字クラス:
[a-z]{3}
は、小文字のアルファベット3文字にマッチします。 - 量指定子:
a*
は、a
が0回以上繰り返されるパターンにマッチします。 - 文字列の先頭・末尾:
^abc
は、文字列がabc
で始まる場合にマッチし、abc$
は、文字列がabc
で終わる場合にマッチします。 - 代替(OR):
cat\|dog
は、cat
またはdog
にマッチします。
演算子の優先順位を理解しておくことで、正確な正規表現を作成できるでしょう。
ネストされたグループ
正規表現では、グループ(())をネストして複雑なパターンを表現できます。
なぜネストされたグループを利用するかというと、より柔軟なマッチングが可能になるからです。
例えば、/(A(B(C|D)E)F)/ のように、グループ内でさらに別のグループを定義して、それぞれに対して個別に量指定子や代替を適用できます。
ネストされたグループを使うことで、入れ子構造や繰り返しのあるパターンを簡潔に表現することができます。
オプションフラグ
正規表現のオプションフラグは、正規表現の挙動を制御するために使用されます。
以下に、オプションフラグの一覧とそれぞれの説明、使用例を示す表を作成しましたので参考にしてください。
フラグ | 説明 | 使用例 | 例の説明 |
---|---|---|---|
i | 大文字・小文字を区別しない | /abc/i | “AbC”、”abc”、”aBc” など、大文字小文字の区別なくマッチする |
g | 全体検索(全てのマッチを検索) | /abc/g | “abcabc” のような文字列で、複数の “abc” がマッチする |
m | 複数行検索 | /^abc$/m | 複数行のテキストで、各行の先頭が “abc” で始まる場合にマッチ |
s | ドットが改行にもマッチする | /a.b/s | “a\nb” でもマッチする(ドットが改行にもマッチ) |
u | Unicode モード | /\p{L}/u | Unicode 文字プロパティを使用できるようになる |
y | スティッキー(先頭固定検索) | /abc/y | 文字列の現在の位置からのみマッチを検索 |
よくある間違いと注意点
よくある間違いについても必ず目をとおしましょう。
なぜなら大抵のエラーは以下のどれかだからです。
- オプションフラグ
- 貪欲マッチと非貪欲マッチ
- 大文字・小文字の無視
エスケープの扱い
正規表現で特殊な意味を持つメタ文字を文字そのものとして扱いたい場合は、エスケープ(\)が必要です。
例えば、.を文字として扱いたい場合は、\.と記述します。同様に、(や[などのメタ文字もエスケープすることで、リテラル文字として扱うことができます。
エスケープを正しく使用することで、意図しないマッチングを防ぐことができます。
貪欲マッチと非貪欲マッチ
正規表現では、マッチングの方法として「貪欲マッチ」と「非貪欲マッチ」があります。
これらの違いを理解することで、正規表現をより効果的に使用できます。
- 貪欲マッチ: 正規表現のデフォルトのマッチング方法で、可能な限り最長の部分にマッチしようとする(例)正規表現
a.*b
が与えられた場合、文字列 “axyzbayb” で最長の “axyzbayb” にマッチ - 非貪欲マッチ: 最短の部分にマッチする方法で、量指定子の後に
?
を追加する(例)正規表現a.*?b
が与えられた場合、文字列 “axyzbayb” で最短の “axyzb” にマッチ
量指定子とは、繰り返しの回数を指定するための記号。例えば、*
は0回以上の繰り返しを表します。
マッチとは、正規表現が与えられた文字列の一部に一致することです。
これらの概念を理解することで、正規表現を使った検索や置換がより簡単で効果的になります。
適切なマッチング方法を選択し、必要なデータを簡単に抽出しましょう。
大文字・小文字の無視
大文字・小文字を無視したい場合は、iフラグを使用します。例えば、/pattern/iのように記述することで、大文字・小文字を区別しないマッチングが可能になります。
まとめ:GASの正規表現はいろいろなコードを参考にしよう
当記事の内容をまとめます。
- 正規表現とは文字列のパターンを表現し、作業効率をあげられる方法のひとつ
- GASで正規表現を使えばさまざまな処理が早くなる
- 正規表現を理解するためにはメタ文字についての理解を深めよう
GASのベースはJavaScriptです。
正規表現はJavaScriptの方法に準じて記述してください。
正規表現を一から覚えるのは大変なので、いろいろなコードを参考にして、効率よくコードを書きましょう。