ハッシュタグにマッチする正規表現
Scrapboxのハッシュタグにマッチする正規表現を求めての試行錯誤ログ。 ちなみに成果は/(?<=\s)#\S+/あるいは/(?<=\s|^)#\S+/である。
/icons/hr.icon
最初の頭のなかでの表現
こんな感じかな〜
/(\s#.*\s|^s#.*\s|\s#.*$)/
「ハッシュタグは、タグになる文字列のひとつ前に空白がなければならない」
「ハッシュタグは、次に続く非ハッシュタグと、空白によって区切られる」
「行の先頭に#があっても、ハッシュタグになる」
「最後が空白ではなく行末であってもハッシュタグになる」
結果:ハッシュタグとなる文字列の前後の空白も正規表現に含まれてしまった。
いわば、_#hash_みたいな文字列ともマッチしてしまう。しかし、理想は#hashである。
↓
/\s#.*\s/
「文中に#が出てきても、それは必ずしもハッシュタグではない」
このことを意識しすぎて、冒頭にやはり\sを付けてしまっている。
結果:やはり前の空白を含んでしまう。
「ハッシュタグは、最後に空白が来て、それによりハッシュタグ以外のものと区別される」
これは間違い。間違った考えにもとづいて\sを末尾につけている。
↓
/(?<=\s)#.*/
第一の突破ポイント:(?<=~)という表現方法を知る。
これにより「ハッシュタグの前には空白がなければならない」を解決
しかし、「空白ごとマッチしてしまう」という問題が発生する。
「任意の文字(.)」には空白(\s)も含まれているのが原因。
↓
/(?<=\s)#\S*/
「任意の文字(.)の繰り返し」ではなく「空白以外の文字(\S)の繰り返し」にする。
これを思いつくために必要な知識
①.には空白も含まれる。
しかし、こうなると、「#」という1文字だけともマッチしてしまう。しかしながら、「#」1文字はハッシュタグではない。
なぜこうなるか:*は、直前の文字の「0回以上の繰り返し」であり、#のあとに空白が来ても、それも含めた文字とマッチしてしまう。
なので、*ではなく+を使わなければならない。
こういうときのために+があるのか。
↓
/(?<=\s)#\S+/
これでほぼ完成だが、一番冒頭に#がある場合のみマッチしない。
なぜなら、冒頭では#の直前に空白(\s)が無いから。
Scrapboxで「タイトルを含めた全文」を検索範囲にする場合などは、これで正しい。
↓
/(?<=\s|^)#\S+/
「空白の次に#が来た場合」と「冒頭に#が来た場合」のどちらにもマッチするならばこれ。
/icons/hr.icon
突破ポイント
(?<=~)を知ったこと。
/\S*/gで「空白以外の任意の文字列の0回以上の繰り返し」とマッチするのだが、これは「空白が有るところの手前まで続く不定文字数の文字列」を意味するということが分かったこと。これにより、「指定したい文字数の末尾に空白も加わってしまうこと」を防げる。
ex. 「abcd efg」という文字列に対してマッチするのは「abcd」と「efg」である。
*は直前の文字が「無い場合」ともマッチしてしまうということを改めて意識したこと。