文章やデータの中から、! や #、( のような半角の記号だけを探したい、まとめて取り除きたい、ということがあります。記号を 1 つずつ検索するのは大変ですが、正規表現 (文字の並びのパターンを表す書き方) の文字クラスを使えば、1 回の検索で済みます。

半角の記号をまとめて表す文字クラス

半角の記号は、次の文字クラスで表せます。

[!-/:-@\[-`{-~]

[ ] は「この中のどれか 1 文字」を表す文字クラスです。a-z のように - でつなぐと、文字コードの範囲を指定できます。半角の英数字と記号は、ASCII という文字コードの表の順に並んでいて、記号は、数字や英字のあいだの 4 か所に分かれて置かれています。

範囲    文字コード     含まれる記号
!-/     0x21〜0x2F    ! " # $ % & ' ( ) * + , - . /
:-@     0x3A〜0x40    : ; < = > ? @
\[-`    0x5B〜0x60    [ \ ] ^ _ `
{-~     0x7B〜0x7E    { | } ~

0x30〜0x39 が数字、0x41〜0x5A が英字の大文字、0x61〜0x7A が小文字なので、そのすき間を 4 つの範囲で拾っている、というわけです。合わせて 32 文字になります。

  • 3 つめの範囲の始まりの [ は、文字クラスの中で特別な意味を持つことがあるので、\[ と書いておきます
  • \ (0x5C) と ] (0x5D) は、この範囲に含まれるので、別に書く必要はありません
  • 空白 (0x20) は含まれません。空白も対象にしたいときは、最初の範囲を [ -/ のように空白から始めます

日本語のフォントでは、\ が円記号 (¥) の形で表示されることがありますが、同じ文字です。

道具によっては、同じ記号を [[:punct:]] (POSIX の文字クラス) と書けるものもあります。ただし、JavaScript の正規表現では使えず、どの文字が含まれるかも道具や設定によって違うことがあります。

全角の記号は含まれない

この文字クラスに一致するのは ASCII の記号だけで、「!」「(」のような全角の記号は含まれません。全角の英数字と記号 (U+FF01〜U+FF5E) は、ASCII の記号と同じ順に並んでいるので、同じ形の範囲で表せます。

[!-/:-@[-`{-~]

句読点の「、」「。」やかぎかっこ「」は、別の場所 (U+3000 から始まる区画) にあるので、これにも含まれません。また、波ダッシュ「〜」(U+301C) は、全角のチルダ「~」(U+FF5E) とは別の文字です。入力する環境によってどちらになるかが違うので、検索で見つからないときは疑ってみてください。

Unicode の文字の種類で指定する

Unicode に対応した正規表現では、文字の種類 (一般カテゴリー) で指定する \p{...} が使えることがあります。

\p{P}   句読点: ! " # % & ' ( ) * , - . / : ; ? @ [ \ ] _ { } や 、 。 「 」 ・ ※ など
\p{S}   記号:   $ + < = > ^ ` | ~ や ¥ 〒 など

半角の記号は、Unicode では句読点 (P) と記号 (S) の 2 つに分かれています。そのため、半角の記号を全部探すには、[\p{P}\p{S}] のように両方を指定します。ただし、こちらは全角の記号や、ほかの言語の記号も含みます。半角だけに絞りたいときは、先の文字クラスを使います。

JavaScript では、u フラグを付けたときに \p{...} が使えます。

const text = "価格は$100です。(税込)";
// 句読点と記号をまとめて取り除く (全角の記号も含む)
console.log(text.replace(/[\p{P}\p{S}]/gu, "")); // 価格は100です税込

置換の例

取り除くだけなら、検索に [!-/:-@\[-`{-~]、置換に空の文字列を指定して、すべて置換します。

全角に直したいときは、エディターの置換では難しいことがあります。多くのエディターの置換では、一致した文字の文字コードを計算して、別の文字にすることができないからです。全角の英数字・記号は、対応する半角の文字コードに 0xFEE0 を足した位置にあるので、スクリプトで処理します。

// 半角の記号を、対応する全角の記号に変える
function toFullwidthSymbols(text) {
  return text.replace(/[!-\/:-@\[-`{-~]/g, (c) =>
    String.fromCharCode(c.charCodeAt(0) + 0xfee0)
  );
}

console.log(toFullwidthSymbols("(注意!)")); // (注意!)

JavaScript の正規表現リテラルの中では、/ を \/ と書いています。

反対に、全角を半角に直すなら、"!".normalize("NFKC") のように Unicode の正規化 (NFKC) を使う方法もあります。ただし、NFKC は「①」を「1」に、半角のカタカナを全角に変えるなど、記号以外の文字も変えるので、結果を確かめてから使ってください。

道具ごとの違いに気をつける

正規表現は、道具によって書き方 (方言) が少しずつ違います。\p{...} が使えるか、文字クラスの中の [ に \ が要るか、置換の文字列で一致した部分を $1 と書くか \1 と書くか、などが変わります。同じエディターでも、開いているファイルの中の検索と、フォルダー全体の検索で、別の仕組みを使っていることがあります。

置換する前に、まず検索だけを行って、一致した箇所の数と場所を確かめましょう。大事なファイルは、置換の前にコピーを取っておくか、Git などで元に戻せる状態にしておくと安心です。

まとめ

  • 半角の記号は [!-/:-@\[-`{-~] でまとめて検索できる (ASCII の 32 文字)
  • 全角の記号は含まれない。全角の英数字・記号は [!-/:-@[-`{-~] で表せる
  • \p{P} (句読点) と \p{S} (記号) は、全角やほかの言語の記号も含む
  • 道具ごとに正規表現の方言が違うので、検索で確かめてから置換する

参考