TypeScriptで文字列のマッチング

TypeScriptで正規表現などを使って文字列をマッチングさせてデータを抽出する方法を確認しました。ここでは、HTMLのテーブルデータ内からデータを抽出する場合を例に確認しています。

※目次をクリックすると目次の下部にコンテンツが表示されます。

サンプルデータ
・テンプレート文字列を使って文字列リテラルを定義
 
〇テンプレート文字列
・バックティック文字(` `)で囲む。
・複数行文字列や文字列内挿機能(${expression})を使用できる。
※参考資料
テンプレート文字列 – JavaScript | MDN
 
○文字列マッチングの対象サンプルデータ

const STR = `
・・・
<a href="#href1" class="#class1">リンク1</a>
<a href="#href2" class="#class2">リンク2</a>
<a href="#href3" class="#class3">リンク3</a>
<table border="1" cellspacing="0" cellpadding="5" width="50%" class="datatable">
  <tbody>
    <tr>
      <th>
        <p align="center">町丁名</p>
      </th>
      <th>
        <p align="center">男</p>
      </th>
      <th>
        <p align="center">女</p>
      </th>
      <th>
        <p align="center">合計</p>
      </th>
    </tr>
    <tr>
      <td>
        <p align="right">芝一丁目</p>
      </td>
      <td>
        <p align="right">722</p>
      </td>
      <td>
        <p align="right">735</p>
      </td>
      <td>
        <p align="right">1,457</p>
      </td>
    </tr>
・・・
    <tr>
      <td>
        <p align="right">合計</p>
      </td>
      <td>
        <p align="right">6,378</p>
      </td>
      <td>
        <p align="right">6,760</p>
      </td>
      <td>
        <p align="right">12,138</p>
      </td>
    </tr>
  </tbody>
</table>
`

正規表現でパターンマッチして文字列抽出
●正規表現について
 
正規表現 – JavaScript | MDN
 
●正規表現でパターンマッチして文字列抽出
 
①Stringクラスのmatchメソッドを使用(部分文字列を抽出する場合は要注意)
 
〇str.match(regexp)
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/match
・全てのマッチを含む配列及び括弧内で捕獲された結果の配列、又はマッチが見つからなかった場合はnullを返す。
・正規表現がgフラグを含んでいる場合、マッチのすべてを含む配列を返す。
この場合、正規表現内に丸括弧を指定し部分文字列を抽出しようとして出来ないようなので要注意。
 
例1)

var result1 = STR.match(/<a\s.*?<\/a>/mg);
for (var i = 0; i < result1.length; i++) {
  console.log(result1[i]);
}
↓
<a href="#href1" class="#class1">リンク1</a>
<a href="#href2" class="#class2">リンク2</a>
<a href="#href3" class="#class3">リンク3</a>

上記サンプルデータ内には三つのリンクタグが含まれているので、
[“1つ目のリンクタグ”,”2つ目”,”3つ目”]
の配列がリターンされる。
 
②正規表現でgフラグをつけて部分文字列を抽出する場合
 
Stringクラスのmatchメソッドでは出来ないので、RegExpのexecメソッドを使用する。
 
〇regexp.exec(str);
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
・マッチが成功した場合配列を返し、正規表現オブジェクトのプロパティを更新する。
・マッチが失敗した場合は、nullを返す。
・gフラグを使用する場合、同じ文字列で成功するマッチを見つけるためにexecメソッドを複数回使うことができる。そのときの検索は、正規表現のlastIndexプロパティで指定された、strの部分文字列から開始される。
 
例2)正規表現内に括弧を使用する場合
・マッチした文字列の中からさらに部分的に文字列を抽出する場合は正規表現に丸括弧を指定する。

var pattern1 = /<a\shref="(.*?)".*>(.*?)<\/a>/gm;
var result3;
while((result3 = pattern1.exec(STR)) != null) {
  console.log(`href:${result3[1]},リンク名:${result3[2]}`);
}
↓
href:#href1,リンク名:リンク1
href:#href2,リンク名:リンク2
href:#href3,リンク名:リンク3

改行文字を含めてマッチング
正規表現に”m”フラグを指定すると”.”が改行文字にもマッチするようになる言語もあるが、JavaScriptではマッチしない。
 
“.”の代わりに[\s\S]などを使用する。
・\s
スペース、タブ、改ページ、改行を含む 1 個のホワイトスペース文字にマッチする。
・\S
ホワイトスペース以外の1文字にマッチする。
 
例3)
var a_tbody = STR.match(/<tbody>[\s\S]*?<\/tbody>/m);

正規表現を使って文字列を置換
〇str.replace(pattern, replacement[, flags])
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace
・文字列中でpatternにマッチする部分全てを文字列replaceで置き換えた文字列を生成して返す。
 
例)テーブルのtdタグ内の不要な文字列を置換して除去
・サンプルデータ内から”tbodyタグ内の文字列を部分文字列で抽出。
・数値データ以外の不要なタグ、改行、スペースなどの文字列を除去。
var a_tbody = STR.match(/<tbody>[\s\S]*?<\/tbody>/m);
var s_tbody = a_tbody[0].replace(/(<p align=”right”>|\r\n|\r|\n|\s|<p>|<\/p>| )/gm, “”);

配列、文字列の存在確認
上記4)の例では、STRリテラルに対するmatchメソッドの結果(配列)に対して、配列に対する参照、replaceメソッドを実行しています。
 
1行目でパターンがマッチされなかった場合は、nullがリターンされるため、2行目の配列に対する参照、Stringオブジェクトのreplaceメソッドはエラーとなります。
 
以下、配列、文字列のチェックなどの方法のいくつかを示します。
 
①ArrayオブジェクトのisArrayメソッド
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
オブジェクトが配列であればtrueを、そうでなければfalseを返す。
 
例)

var a_tbody = STR.match(/<tbody>[\s\S]*?<\/tbody>/m);
if(Array.isArray(a_tbody)) {
・・・

 
②typeof
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/typeof
・評価を行われないままの状態のオペランドのデータ型を示す文字列を返す。
・文字列(プリミティブ)を評価した場合は、”string”を返すので、文字列の判定ができる。ただし、Stringオブジェクトの場合は、”object”を返すので要注意。Stringオブジェクトの判定をする場合はinstanceofメソッドなどを使用する。
 
③instanceof
https://developer.mozilla.org/ja/docs/JavaScript/Reference/Operators/instanceof
・objectのプロトタイプチェインでconstructor.prototypeの存在を確認する。
・以下のようにしてStringオブジェクトの判定ができる。
var newStr = new String(“String created with constructor”);
newStr instanceof String; // true を返す
ただし、文字列の場合はfalseを返すので要注意。
var simpleStr = “This is a simple string”;
simpleStr instanceof String; // プロトタイプチェーンをチェックして undefined が見つかるため、false を返す
 
例)

var a_tbody = STR.match(/<tbody>[\s\S]*?<\/tbody>/m);
if(Array.isArray(a_tbody)) {
  if(typeof a_tbody[0] === 'string' || a_tbody[0] instanceof String){
    var s_tbody = a_tbody[0].replace(/(<p align="right">|\r\n|\r|\n|\s|<p>|<\/p>| )/gm, "");

正規表現を使ってパターンマッチして真偽の判定
RegExpのtestメソッドを使用する。
 
〇regexObj.test(str)
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
・正規表現と対象の文字列の間のマッチを調べるための検索を実行し、結果を示す真偽値を返す。
 
例)テーブル内のtdタグ内のデータを抽出するが、項目名に(総数|合計|計)が含まれる行のデータは除外する

var a_tbody = STR.match(/<tbody>[\s\S]*?<\/tbody>/m);
if(Array.isArray(a_tbody)) {
  var chk: any | string = a_tbody[0];
  if(typeof chk === 'string' || chk instanceof String){
    var s_tbody = a_tbody[0].replace(/(<p align="right">|\r\n|\r|\n|\s|<p>|<\/p>| )/gm, "");
    var a_tr = s_tbody.match(/<tr>[\s\S]*?<\/tr>/gm);
    for (var i = 0; i < a_tr.length; i++) {
      var a_td = a_tr[i].match(/<td>[\s\S]*?<\/td>/gm); 
      if(Array.isArray(a_td)) {
        var pattern2 = /(総数|合計|計)/;
        if (!pattern2.test(a_td[0])) {
          a_td[0] = a_td[0].replace(/(<td>|<\/td>)/gm, "");
          a_td[1] = a_td[1].replace(/(<td>|<\/td>)/gm, "");
          a_td[2] = a_td[2].replace(/(<td>|<\/td>)/gm, "");
          a_td[3] = a_td[3].replace(/(<td>|<\/td>)/gm, "");
          console.log(`${a_td[0]}の男は${a_td[1]}人、女は${a_td[2]}人、合計${a_td[3]}人です。\n`);
        }
      }
    }
  }
}

関連記事の目次

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です