正規表現 -test- -match-

構文 : 正規表現オブジェクト.test(文字列)
戻り値: 真偽値

構文 : 文字列.match(正規表現) 
戻り値: 配列 or null
     配列の0番目の要素にマッチした文字列が入っている

フラグ /正規表現/i  
 g グローバル検索(有:全てを返す。無:最初に一致したものを返す)  
 i 大文字小文字区別無し   
 m 複数行検索  
 y 位置指定検索

文字や数字を検索 \w
文字や数字以外を検索 \W
word

console.log("ABC_abc_ABC?".match(/\w/g));    // "A", "B", "C", "_", "a", "b", "c", "_", "A", "B", "C"
console.log("ABC_abc_ABC?".match(/\W/g));    // ?

数字を検索  \d
数字以外を検索  \D
digit character

console.log("ABC123_abc_ABC?".match(/\d/g));   // 1,2,3
console.log("ABC123?".match(/\D/g));   // A,B,C,?

改行文字を検索   \n
newline

console.log("AB\nC1\n23?".match(/\n/g));   // 改行文字,改行文字

キャリッジリターン(復帰文字)を検索  \r
carriage return

console.log("AB\r\nC1\r\n23?".match(/\r/g));   // 復帰文字,復帰文字

タブを検索  \t
tab

console.log("AB\tC1\t23?".match(/\t/g));   // タブ,タブ

空白を検索  \s
空白以外を検索  \S
space
空白:半角/全角スペース、タブ、改行、改ページ

console.log("A B\t C1\t23?".match(/\s/g));   // スペース,タブ,スペース,タブ

単語の境目を検索  \b
単語以外の境目を検索  \B
word boundary
単語の境目:単語を構成する文字(a-z,A-Z,0-9,_) とそれ以外の文字との境目

console.log("This is a pen".match(/\b/g));
console.log("This is a pen".match(/\bT/g));
console.log("This is a pen".match(/s\b/g));
console.log("This is a pen".match(/\bi/g));
console.log("This is a pen".match(/\ba/g));
console.log("This is a pen".match(/a\b/g));
console.log("This is a pen".match(/\bp/g));
console.log("This is a pen".match(/n\b/g));

●数量詞

先頭(行頭)を検索  ^

console.log("this is \nthis is a".match(/^this/gm));   // this,this

末尾(行末)を検索  $

console.log("this is\nthis is".match(/is$/gm));   // is,is

特定の値が後に続いている文字列を検索  (?=xxx)

console.log("this is\nthis is".match(/th(?=is)/g));   // th,th

特定の値が後に続いていない文字列を検索  (?!xxx)

console.log("this is\nthis is".match(/th(?!is)/g));   // null

n回の繰返し  {n}

console.log("aaa a aa aaa a".match(/a{2}/g));   // aa,aa,aa
console.log("aaa a aa aaa a".match(/a{3}/g));   // aaa,aaa

n回以上の繰返し   {n,}

console.log("aaa a aa aaa a".match(/a{2,}/g));   // aaa,aa,aaa

n回以上m回以下の繰返し  {n,m}

console.log("AC ABC ABBC ABBBC".match(/AB{0,2}C/g));   // AC,ABC,ABBC

1回以上の繰返し  +

console.log("aaa a aa aaa a".match(/a+/g));   // aaa,a,aa,aaa,a

0回以上の繰返し  *

console.log("aaa a aa".match(/a*/g));   // aaa,スペース,a,スペース,aa

0もしくは1回  ?

console.log("aaa a aa".match(/aa?/g));   // aa a a aa

●ブラケットを用いた検索

いずれかの1文字を検索する  []    
いずれかの文字以外を検索 [^]

console.log("abc def ghi".match(/[aei]/g));   // a e i

指定した範囲の値を検索 [0-9A-Za-z]
アスキーコード順 数字 → 英大文字 → 英小文字

console.log("abc def ghi".match(/[0-9A-Za-z]/g));   // a,b,c,d,e,f,g,h,i

最長マッチと最短マッチ
通常「 + 」や「 * 」を使った正規表現は可能なかぎり長い文字列をマッチさせようとする。 それぞれの記号の後に「 ? 」をつけることにより可能なかぎり短い文字列にマッチするようになる

console.log("abc/efg/hij/klm".match(/abc\/(.*)\//));
console.log("abc/efg/hij/klm".match(/abc\/(.*?)\//));
// 例:
// 郵便番号  n回の繰返し {n}
console.log("215-3265".match([0-9]{3}-[0-9]{4});

// 時間  最長マッチと最短マッチ
console.log("1:3:25".match(/^([01]?[0-9]|[2][0-4]):([0-5]?[0-9]):([0-5]?[0-9])$/));

[\s\S]
\sは空白で\Sは空白以外だから、2つ合わせると「全ての文字」という意味になる。全ての文字という意味の記号として.があるが、.は改行文字にマッチしないので[\s\S]は.よりも範囲が広い。(\sが改行文字にマッチする)これは逆の意味を持つ2つの記号なら何でもよく、[\d\D]などでも同じことができる。

console.log(/abc/.test("abcdefgh"));  // true
console.log(/xyz/.test("abcdefgh"));  // false
console.log(/abc|xyz/.test("abcdefgh"));  // true (abc または xyzの文字列)
console.log(/[ag]/.test("abcdefgh"));  // true (a,gの1文字)
console.log(/[a-g]/.test("abcdefgh"));  // true (aからgの1文字)
console.log(/[^a-h]/.test("abcdefgh"));  // false (aからh以外の1文字)

グループの参照を使ってタグの中身を取得する

const html = `<h1>見出し1</h1>
<h2>見出し2</h2>
<h3>見出し3</h3>
<header>ヘッダー</header>`;

let ma = html.matchAll(/<(h[1-6])>(.+)<\/\1>/g);

for (const matched of ma) {
  console.log(matched[0], matched[1], matched[2]);
}

前方参照
文字列AAを検索、ただし直後に文字列BBがあるもの

AA(?=BB)

前方参照(否定)
文字列AAを検索、ただし直後に文字列BBが無いもの

AA(?!BB)

後方参照
文字列BBを検索、ただし直前に文字列AAがあるもの

(?<=AA)BB

後方参照(否定)
文字列BBを検索、ただし直前に文字列AAが無いもの

(?<!AA)BB