- 技術 💻
エスケープとは?意味とHTML・JS・正規表現・SQL・CSVの書き方(変換ツール)
結論
エスケープとは、文字列の中で「区切り」や「命令」として特別な意味を持つ記号を、ただの文字として扱えるように決まった形へ書き換えることです。HTML では < を < に、JavaScript の文字列では " を \" に、SQL の文字列では ' を '' に書き換えます。どの書き方になるかは、文字列を「どこに入れるか」で決まります。
この記事でわかること
- エスケープの意味(ふだんの「逃げる」との関係)と、エスケープ文字・エスケープシーケンス・Esc キーの違い
- HTML・JavaScript/JSON・正規表現・SQL・CSV・Python・Java・PHP・シェルの書き方を、実際に動かした出力つきで
- 二重エスケープ(&lt;)やエスケープ忘れで出るエラーの原文と、行き先から選ぶ判断表
エスケープ変換を読み込み中です。
ツールの使い方:入力欄に文字列を貼ると、その場で結果が出ます。
- 向きを選ぶ:「エスケープする」と「元に戻す(アンエスケープ)」を切り替えます。
- 種類を選ぶ:HTML・JavaScript/JSON の文字列・正規表現・SQL の文字列・CSV の1項目の5種類です。
- HTML:
&<>の3文字だけにするか、"'も含めた5文字にするかを「" と ' も変換する」で選べます。エスケープした結果の下に、ブラウザでの見え方(タグとしては動かず、文字として表示)も出ます。元に戻すときは<©などよく使う約40個の名前つき文字参照と、あ・あの数値の形に対応し、知らない名前はそのまま残して個数を示します。 - JavaScript/JSON:
"\改行・タブなどを\付きの形にします。元に戻すときは\n\t\"\\\u3042\x41などを文字に戻し、\uの後ろが16進数4桁でないときは何文字目かを示します。 - 正規表現は記号の前に
\を付け、SQL は'を''に重ねて全体を'で囲み、CSV は RFC 4180 の形(カンマ・"・改行を含むときだけ"で囲み、中の"を""に)にします。 - 結果は「コピー」ボタンでコピーできます。見本ボタン(HTML のタグ・< を戻す・改行と " を含む文字・正規表現の記号・SQL の '・CSV のカンマ)で、よくある入力を試せます。入力した内容はこの端末の中だけで変換し、どこにも送信しません。
この記事で実際に動かしたもの:上のツール(Chromium で表示して20通りの入力を確認)、Python・Node.js・Java・PHP の標準の関数、127.0.0.1 に立てた PostgreSQL 16 と SQLite、bash、Chromium での HTML の表示。
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| エスケープの意味 | 特別な意味の記号を「ただの文字」に書き換えること | エスケープとは |
| エスケープ文字とは | 書き換えの目印になる文字。\・&・'(SQL)など | エスケープ文字の一覧表 |
| HTML のエスケープ | & < > " ' を & < > " ' に | HTMLのエスケープ |
| 文字列の中に " や改行を書きたい | \" \n。JSON は JSON.stringify・json.dumps に任せる | JavaScript・JSONのエスケープ |
| 正規表現で . や $ を文字として探す | \. \$。re.escape・Pattern.quote・preg_quote | 正規表現のエスケープ |
| SQL で ' を含む文字列 | 'It''s' のように重ねる。アプリはプレースホルダ | SQLのエスケープ |
| CSV でカンマを含む値 | "東京都港区, 六本木" と " で囲む | CSVのエスケープ |
| < と表示されてしまう | 二重エスケープ。エスケープを1か所にする | 二重エスケープとエスケープ忘れ |
| Esc キーとの違い | 名前の由来は同じだが別物 | エスケープとEscキー・エンコードの違い |
flowchart LR
A{行き先}
A --> C[HTML:文字参照]
A --> D[JS:前に \]
A --> E[正規表現:前に \]
A --> F[SQL:引用符を重ねる]
A --> G[CSV:引用符で囲む]
確認環境:Ubuntu 24.04.5 LTS の上で、Python 3.13.18(html・json・re・csv・shlex・sqlite3。SQLite 3.53.1)、Node.js 22.23.4、OpenJDK 21.0.12.1(javac・java)、PHP 8.3.6、bash 5.2.21 の標準の関数・コマンドで同じ文字列を変換し、出力とエラーをそのまま載せました。SQL は作業用のディレクトリに PostgreSQL 16.15 を立て、127.0.0.1 だけで待ち受けて psql から実行しました。HTML の見え方は Playwright から Chromium 153.0.8010.12 を起動し、自作のページの textContent と input の value を読み取りました。記事内ツールは、テーマの code.js を読み込んだページを Chromium(幅390px)で開き、5種類・2方向で20通りの入力を確かめました。MySQL のバックスラッシュの扱いと PowerShell のエスケープ文字は、公式ドキュメントの範囲で書いています。外部のサービスには接続していません(確認日 2026年11月9日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「エスケープとは?意味とHTML・JS・正規表現・SQL・CSVの書き方(変換ツール)」
エスケープとは(意味をひとことで)
この節では、エスケープという言葉の意味と、ふだんの「エスケープ」との関係が分かります。
エスケープ(escape)は、文字列の中で特別な役目を持つ記号を、その役目から「逃がして」ただの文字として扱わせることです。英語の escape は「逃げる・抜け出す」で、IT では「記号を本来の役目から抜け出させる」という意味で使われます。エスケープする処理を「エスケープ処理」、目印に使う文字(\ など)を「エスケープ文字」と呼びます。
たとえば JavaScript で "彼は "OK" と言った" と書くと、2つ目の " で文字列が終わったと読まれ、エラーになります。"彼は \"OK\" と言った" と \ を付けると、" は「文字列の終わり」という役目から外れ、ただの文字になります。
| ふだんの意味 | IT・プログラミングでの意味 | |
|---|---|---|
| エスケープ | 逃げる・脱出する(脱出ゲーム、エスケープルーム) | 記号を特別な役目から外し、ただの文字として扱わせること |
| 何から逃げるか | 部屋・危険・束縛 | 「文字列の終わり」「タグの始まり」「何にでも一致」などの役目 |
| 身近な例 | 非常口から外へ出る | < を < と書くと、タグにならず < と表示される |
同じ「エスケープ」でも、場面によって指すものが違います。検索してたどり着いた場面と照らし合わせると迷いません。
| 場面 | エスケープが指すもの | 例 |
|---|---|---|
| 文字列・HTML・SQL を書くとき | 特別な記号をただの文字にする書き換え(この記事の主題) | < \" '' |
| 文字列の中の改行やタブ | 見えない文字を目印付きで書く「エスケープシーケンス」 | \n(改行) \t(タブ) |
| キーボード | 操作を取り消す・閉じる Esc キー | ダイアログを閉じる、Vim で入力を抜ける |
| ターミナルの色や位置の指定 | ESC 文字(制御文字の27番)から始まる命令の並び | 文字に色を付ける命令 |
| Java などの最適化 | 「エスケープ解析」。オブジェクトがメソッドの外へ出ていくかの解析 | JVM の JIT コンパイラの最適化 |
1エスケープ(処理)
記号を書き換える行為そのもの。「HTML エスケープする」「エスケープ漏れ」のように使います。
2エスケープ文字
書き換えの目印になる文字。多くの言語では \(バックスラッシュ)、HTML では &、SQL では引用符そのもの。
3アンエスケープ
エスケープした形を元の文字に戻すこと。デコード、アンエスケープ、エスケープ解除とも呼びます。
次の節では、なぜこうした書き換えが必要になるのかを、2つの役割に分けて見ます。
エスケープが必要になる理由(区切りと中身がぶつかる)
この節では、エスケープが必要になる仕組みと、エスケープの2つの役割が分かります。
エスケープが必要になるのは、「区切りや命令に使う記号」と「中身として書きたい文字」が同じ記号だからです。HTML は < でタグの始まりを、JavaScript は " で文字列の端を、CSV は , で項目の区切りを表します。中身にも同じ記号を書きたいとき、プログラムはどちらの意味か区別できません。そこで「中身のほうは別の形で書く」と決めておくのがエスケープです。
役割1:意味を打ち消す
\" … 文字列の終わりではなく、ただの "
< … タグの始まりではなく、ただの <
\. … 正規表現の「任意の1文字」ではなく、ただの .
役割2:意味を足す
\n … ただの n ではなく、改行
\t … ただの t ではなく、タブ
\u3042 … 文字コード U+3042 の「あ」
役割2のように、キーボードで打ちにくい文字や見えない文字(改行・タブ・NUL など)を、目印と普通の文字の組み合わせで書く形をエスケープシーケンスと呼びます。どちらの役割でも、「目印の文字」が先頭に付く点は同じです。
目印の文字そのものを書きたいときは、目印を2つ重ねます。\ を1つ書きたいときは \\、HTML で & を書きたいときは &、SQL で ' を書きたいときは '' です。「目印そのものもエスケープする」は、どの場所にも共通する決まりで、ここを忘れると次の節以降で見るエラーや表示崩れが起きます。
続いて、場所ごとのエスケープ文字を一覧表で見ます。
エスケープ文字の一覧表(場所別)
この節では、HTML・JavaScript・正規表現・SQL・CSV・シェルで、どの文字がエスケープ文字になり、何をどう書き換えるかが分かります。
エスケープ文字は場所ごとに違います。同じ ' でも、JavaScript なら \'、SQL なら ''、HTML の属性なら ' です。下の表の「書き換えた形」は、この記事の各節で実際に動かして確かめたものです。
| 場所 | エスケープ文字 | 書き換える主な文字 | 書き換えた形 |
|---|---|---|---|
| HTML の本文 | &(文字参照) | & < > | & < > |
| HTML の属性の値 | & | 上の3つ + " ' | " '(') |
| JavaScript・JSON の文字列 | \ | " \ 改行 タブ | \" \\ \n \t \u3042 |
| Python・Java・C 系の文字列 | \ | 引用符 \ 改行 | \' \" \\ \n |
| 正規表現 | \ | . * + ? ^ $ ( ) [ ] { } | | \. \$ \( など |
| SQL の文字列 | '(重ねる) | ' | 'It''s' |
| SQL の識別子 | "(MySQL は `) | 予約語・空白を含む名前 | "order" |
| CSV の1項目 | "(重ねる) | , " 改行 | "a,b" "He said ""hi""" |
| bash | \ と引用符 | 空白 $ ' " | my\ file.txt 'It'\''s' |
| PowerShell | `(バッククォート) | 改行 タブ("…" の中だけ) | `n `t |
方式は大きく3つです。
- 目印を前に付ける方式:
\を前に付ける(JavaScript・Python・Java・正規表現・bash)。 - 名前や番号で書く方式:
&名前;や&#番号;で書く(HTML・XML の文字参照)。 - 同じ記号を重ねる方式:
'を''、"を""にする(SQL・CSV)。
次の節から、場所ごとに実際の出力を見ていきます。まずは検索でいちばん多い HTML です。
HTMLのエスケープ(& < > " ' と文字参照)
この節では、HTML で書き換える5つの文字と、エスケープしないと表示がどう崩れるかを、Chromium で表示した結果で確かめられます。
HTML では & < > " ' の5文字を、文字参照(& < > " ')に書き換えます。本文に入れるだけなら & < > の3文字、属性の値("…" の中)に入れるなら " ' も書き換えます。どちらにも使えるように、いつも5文字を書き換えるのがいちばん簡単です。
| 文字 | 文字参照(名前) | 文字参照(番号) | 書き換える理由 |
|---|---|---|---|
& | & | & | 文字参照の始まりの目印だから。いちばん先に書き換える |
< | < | < | タグの始まりと読まれる |
> | > | > | タグの終わり。本文では必須ではないが、そろえて書き換える |
" | " | " | 属性の値を " で囲んでいると、そこで値が終わる |
' | ' | ' | 属性の値を ' で囲んでいると、そこで値が終わる |
エスケープしないとどう表示されるか(Chromium で確かめた結果)
同じ文章を、エスケープせずに書いた場合とエスケープした場合で、Chromium 153 に表示させ、画面に出る文字(textContent)と、できた要素の数を読み取りました。
<p>タグの例:<b>太字</b>と書きます</p>
<p>タグの例:<b>太字</b>と書きます</p>
<p>if (a<b) { x = 1 }</p>
<p>?q=A&B©=1</p>
<input value="彼は "OK" と言った">
<input value="彼は "OK" と言った">
| 書いた HTML | 画面に出た文字 | 起きたこと |
|---|---|---|
<b>太字</b>(エスケープなし) | タグの例:太字と書きます | <b> がタグとして働き、説明したい <b> が消えた(子要素1個) |
<b>太字</b> | タグの例:太字と書きます | 狙いどおり文字として表示(子要素0個) |
if (a<b) { x = 1 } | if (a | <b からがタグと読まれ、後ろが太字の要素になって消えた |
?q=A&B©=1 | ?q=A&B©=1 | © が「©」と読まれ、URL が変わった |
value="彼は "OK" と言った" | 彼は (ここで切れる) | 値は「彼は 」だけ。OK" などは別の属性名になった |
value="彼は "OK" と言った" | 彼は "OK" と言った | 正しく表示 |
3行目と4行目は見落としやすい例です。a<b のように < のすぐ後ろが英字だとタグと読まれ、1 < 2 のように後ろが空白なら文字のまま残りました。また、URL の ©=1 のようにセミコロンが無くても © は「©」と読まれます(HTML の仕様で、以前からある一部の名前は ; 無しでも認められています)。HTML の中に URL を書くときも & は & にします。
言語・ライブラリの HTML エスケープ関数
手で置き換えるより、言語の関数を使うのが確実です。同じ文字列を Python と PHP で変換しました。
import html
s = '<a href="/search?q=A&B">"C++" & \'Java\'</a>'
print(html.escape(s))
print(html.escape(s, quote=False))
print(html.unescape("<p>&copy; © あ あ &lt;"))
<a href="/search?q=A&B">"C++" & 'Java'</a>
<a href="/search?q=A&B">"C++" & 'Java'</a>
<p>© © あ あ <
<?php
echo htmlspecialchars($s), "\n";
echo htmlspecialchars($s, ENT_NOQUOTES), "\n";
echo htmlspecialchars("< &"), " | ", htmlspecialchars("< &", ENT_QUOTES, 'UTF-8', false), "\n";
<a href="/search?q=A&B">"C++" & 'Java'</a>
<a href="/search?q=A&B">"C++" & 'Java'</a>
&lt; &amp; | < &
- Python の
html.escapeは、既定(quote=True)で'を'にします。PHP のhtmlspecialcharsは'でした。書き方は違っても、ブラウザで表示すると同じ'になります。 - PHP 8.1 から、
htmlspecialcharsの既定のフラグはENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401で、'も変換されます(PHP マニュアル)。 - PHP の4番目の引数
double_encodeをfalseにすると、すでに<になっている部分は変換しません。ただし、二重エスケープの根本の直し方は「エスケープを1か所にする」ことです(後の節)。
JavaScript では textContent を使う
JavaScript で画面に文字を入れるときは、自分でエスケープするより、文字として入れる API を選ぶほうが確実です。Chromium で同じ文字列を2通りに入れました。
const t = document.createElement('p');
t.textContent = '<b>太字</b>'; // 文字として入る
console.log(t.innerHTML, t.children.length);
const h = document.createElement('p');
h.innerHTML = '<b>太字</b>'; // HTML として解釈される
console.log(h.textContent, h.children.length);
<b>太字</b> 0
太字 1
textContent に入れた文字列は、ブラウザが自動でエスケープして扱い、要素は1つも作られませんでした。React の {value}、Vue の {{ value }}、Django・Jinja2・Thymeleaf などのテンプレートも、既定で同じように自動エスケープします。アプリで利用者の入力などを画面に出すときは、この自動エスケープに任せ、HTML として解釈させる書き方(innerHTML や React の dangerouslySetInnerHTML)は必要な場面に限ります。React で HTML を入れる場合の注意は、関連記事「dangerouslySetInnerHTMLの使い方とサニタイズ」で扱っています。
次の節では、HTML と並んで多い JavaScript・JSON の文字列のエスケープを見ます。
JavaScript・JSONの文字列のエスケープ(\n・\"・\u)
この節では、JavaScript と JSON の文字列の中で使うエスケープシーケンスと、JSON.stringify に任せたときの出力が分かります。
JavaScript と JSON の文字列では、\ がエスケープ文字です。文字列を囲んでいる引用符と同じ引用符、\ そのもの、改行やタブなどの見えない文字を、\ 付きの形で書きます。
| 書き方 | 意味 | JavaScript | JSON |
|---|---|---|---|
\" | "(二重引用符) | 使える | 使える(必須) |
\' | '(単一引用符) | 使える | 使えない(エラー) |
\\ | \ そのもの | 使える | 使える |
\n \r \t | 改行(LF)・復帰(CR)・タブ | 使える | 使える |
\u3042 | U+3042(あ) | 使える | 使える |
\u{1F600} | U+1F600(😀) | 使える | 使えない(\uD83D\uDE00 と書く) |
\x41 | 16進数2桁の文字(A) | 使える | 使えない |
Node.js 22 で実際に動かしました。
const s = '彼は "OK" と言った。\n次\tタブ\\';
console.log(JSON.stringify(s));
console.log(s.length);
console.log('It\'s', "It's", `It's ${1 + 1}`);
console.log('\u3042', '\u{1F600}', '\x41');
console.log(String.raw`C:\temp\new`);
"彼は \"OK\" と言った。\n次\tタブ\\"
19
It's It's It's 2
あ 😀 A
C:\temp\new
JSON.stringifyに任せると、"\改行・タブが正しくエスケープされます。JSON を文字列の連結で組み立てると、値に"や改行が入ったときに壊れます。s.lengthが19なのは、\n\t\\がそれぞれ1文字だからです。エスケープした形はソースコード上の書き方で、メモリ上の文字はその1文字です。'It\'s'と書く代わりに、引用符の種類を変える("It's")、テンプレートリテラル(`…`)を使う方法もあります。String.rawを付けたテンプレートリテラルは、\をエスケープ文字として扱わずにそのまま残します。Windows のパスを書くときに便利です。
Python と PHP の JSON は日本語を \u にする
import json
print(json.dumps('彼は "OK" と言った。\n次\tタブ\\'))
print(json.dumps('彼は "OK"', ensure_ascii=False))
"\u5f7c\u306f \"OK\" \u3068\u8a00\u3063\u305f\u3002\n\u6b21\t\u30bf\u30d6\\"
"彼は \"OK\""
PHP の json_encode
既定 : {"msg":"\u5f7c\u306f\"OK\"\/x"}
JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES: {"msg":"彼は\"OK\"/x"}
Python の json.dumps と PHP の json_encode は、既定で日本語を \u5f7c のような形に、PHP は / も \/ にエスケープします。JSON として正しい形なので、読み込めば元の文字に戻ります。人が読むログや設定ファイルで日本語のまま出したいときは、ensure_ascii=False や JSON_UNESCAPED_UNICODE を指定します。JSON の読み書き全体は、関連記事「JSON.parseとJSON.stringifyの使い方|エラー原因と整形」で扱っています。
次の節では、\ の扱いがさらにややこしくなる正規表現を見ます。
正規表現のエスケープ(. や $ を文字として探す)
この節では、正規表現で記号を文字として探す書き方と、各言語のエスケープ関数の出力が分かります。
正規表現では . * + ? ^ $ ( ) [ ] { } | \ が特別な意味を持つので、文字として探すときは前に \ を付けます。たとえば . は「任意の1文字」、$ は「行の終わり」です。エスケープしないと、狙いと違うものに一致したり、何にも一致しなかったりします。
import re
print(re.escape("price: $10.00 (tax+)"))
print(re.findall(re.escape("$10.00"), "A $10.00 B $10500"))
print(re.findall("$10.00", "A $10.00 B $10500"))
price:\ \$10\.00\ \(tax\+\)
['$10.00']
[]
エスケープしない "$10.00" は、先頭の $ が「行の終わり」と読まれ、何にも一致しませんでした(結果は空のリスト)。re.escape を通すと $ と . に \ が付き、$10.00 だけに一致しました。re.escape は空白にも \ を付けますが、結果は同じです。
JavaScript・Java・PHP のエスケープ関数
| 言語 | 関数 | 「price: $10.00 (tax+)」の結果 |
|---|---|---|
| Python | re.escape(s) | price:\ \$10\.00\ \(tax\+\) |
| JavaScript(Chromium 153) | RegExp.escape(s) | \$10\.00\x20\(tax\+\)(「$10.00 (tax+)」で実行) |
| JavaScript(Node.js 22) | RegExp.escape は undefined | MDN の関数で price: \$10\.00 \(tax\+\) |
| Java | Pattern.quote(s) | \Q$10.00\E(「$10.00」で実行) |
| PHP | preg_quote(s, '/') | price\: \$10\.00 \(tax\+\) |
RegExp.escape は、MDN で「Baseline 2025」(2025年5月以降の主要ブラウザーの最新版で動く)とされる新しい関数です。Chromium 153 では動き、Node.js 22.23.4 では undefined でした。使えない環境では、MDN に載っている次の関数を使います。
const escapeRegExp = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
console.log(escapeRegExp('price: $10.00 (tax+)'));
console.log('A $10.00 B $10500'.match(new RegExp(escapeRegExp('$10.00'), 'g')));
price: \$10\.00 \(tax\+\)
[ '$10.00' ]
Java の Pattern.quote は、記号の1つずつに \ を付けるのではなく、全体を \Q と \E で囲みます。その間は「すべて文字として扱う」という意味です。
置換する側の $ と \ もエスケープが要る
正規表現の置換では、置換後の文字列にも特別な記号があります。JavaScript の $&(一致した部分)や Java の $1(グループ)です。
JavaScript 'a-b'.replace('-', '$&$&') → a--b ($& が「一致した -」になる)
JavaScript 'a-b'.replace('-', () => '$&') → a$&b (関数で返すと文字のまま)
Java "a-b".replaceAll("-", "$") → java.lang.IllegalArgumentException: Illegal group reference: group index is missing
Java Matcher.quoteReplacement("$1\x") → \$1\\x
置換後の文字列に利用者の入力などを入れるときは、JavaScript なら関数で返す、Java なら Matcher.quoteReplacement を通します。正規表現の記号の一覧は、関連記事「正規表現 早見表|記号一覧・言語別の違い・実用パターン(実行結果つき)」で扱っています。
次の節では、引用符を重ねる方式の代表である SQL を見ます。
SQLのエスケープ('を''に重ねる)
この節では、SQL の文字列に ' を入れる書き方、PostgreSQL と MySQL の違い、テーブル名などの識別子のエスケープが分かります。
SQL の文字列は ' で囲むので、中に ' を書くときは '' と2つ重ねます。これは SQL の標準の書き方で、PostgreSQL・MySQL・SQLite・Oracle・SQL Server のどれでも通ります。PostgreSQL 16 で実行しました。
SELECT 'It''s a pen' AS a, length('It''s a pen') AS len;
SELECT E'tab[\t] It\'s' AS e_string;
SHOW standard_conforming_strings;
SELECT 'C:\temp\new' AS backslash_plain;
SELECT $$It's "dollar" quoted$$ AS dollar;
a | len
------------+-----
It's a pen | 10
e_string
----------------
tab[ ] It's
standard_conforming_strings
-----------------------------
on
backslash_plain
-----------------
C:\temp\new
dollar
----------------------
It's "dollar" quoted
'It''s a pen'の長さは10。重ねた''はデータとしては'1文字です。- PostgreSQL は
standard_conforming_stringsがon(9.1 以降の既定)で、ふつうの'…'の中の\はただの文字です(C:\temp\newがそのまま出た)。\tなどを使いたいときはE'…'と書きます。 - ドル記号を2つ並べて囲む書き方(ドル引用符)は PostgreSQL 独自のもので、中の
'を重ねずに書けます。関数の本体を書くときによく使います。
MySQL は既定で '…' の中の \ をエスケープ文字として扱います。MySQL 8.4 のリファレンスマニュアルでは、\' \" \n \t \\ \0 などが一覧になっており、SQL モード NO_BACKSLASH_ESCAPES を有効にすると、この扱いをやめます。同じ 'C:\temp\new' でも、PostgreSQL と MySQL(既定)で結果が変わるということです。PostgreSQL で MySQL の書き方 'It\'s' を実行すると、ERROR: unterminated quoted string at or near "';" になりました。どちらでも同じ結果にしたいなら、' は '' で書き、\ は使わないのが確実です。
エスケープを忘れたときのエラー
PostgreSQL 16:
ERROR: syntax error at or near "a"
LINE 1: SELECT 'It's a pen';
^
SQLite 3.53.1(Python の sqlite3):
sqlite3.OperationalError: near "s": syntax error
'It' で文字列が終わり、続く s は列の別名、a で文法エラーになりました。エラーの位置(^)が ' の少し後ろを指すのが、エスケープ忘れの見分け方です。
テーブル名・列名(識別子)のエスケープ
CREATE TABLE order (id int);
ERROR: syntax error at or near "order"
CREATE TABLE "order" (id int, "select" text); → CREATE TABLE
SELECT quote_literal('It''s'), quote_ident('order'), quote_ident('name');
'It''s' | "order" | name
order や select のような予約語をテーブル名・列名に使うときは、PostgreSQL・SQLite・標準 SQL では "…"、MySQL では `…` で囲みます。値は '、名前は " と、囲む記号が違う点に注意します。LIKE の % _ を文字として探す ESCAPE 句は、関連記事「SQL LIKE部分一致とエスケープ|%・_の扱いをDB別にコピペ解説」で扱っています。
アプリから値を渡すときはプレースホルダ
c.execute("insert into t values ('It''s a pen')") # 手で重ねる
c.execute("insert into t values (?)", ("It's a pen",)) # プレースホルダ
print(c.execute("select name, length(name) from t").fetchall())
[("It's a pen", 10), ("It's a pen", 10)]
どちらも同じ値が入りました。アプリから SQL に値を渡すときは、文字列をつなげて SQL を組み立てず、プレースホルダ(? や :name)を使います。値の中の ' はドライバーが正しく扱うので、自分でエスケープする場面がなくなります。手で '' にするのは、SQL を直接書いて実行するときです。
次の節では、同じく「重ねる」方式の CSV を見ます。
CSVのエスケープ(カンマ・"・改行を含む値)
この節では、CSV の値にカンマや " や改行が入るときの書き方(RFC 4180)と、Python・PHP の出力が分かります。
CSV では、カンマ・"・改行を含む値を " で囲み、中の " は "" に重ねます。CSV の書き方をまとめた RFC 4180 の決まりです。囲まないと、値の中のカンマで列がずれます。
import csv, io
buf = io.StringIO(); w = csv.writer(buf, lineterminator="\n")
w.writerow(["1", '東京都港区, 六本木', 'He said "hi"', "改行\nあり", "普通"])
print(buf.getvalue(), end="")
print(next(csv.reader(io.StringIO(buf.getvalue()))))
1,"東京都港区, 六本木","He said ""hi""","改行
あり",普通
['1', '東京都港区, 六本木', 'He said "hi"', '改行\nあり', '普通']
csv.writer は、カンマ・"・改行を含む3つの値だけを " で囲み、「普通」と「1」は囲みませんでした。読み戻すと5項目に戻り、改行を含む値も1項目のままです。PHP の fputcsv も同じ形でした。
PHP fputcsv : 1,"東京都港区, 六本木","He said ""hi""",普通
| 値 | CSV に書く形 | 理由 |
|---|---|---|
普通の値 | 普通の値 | 特別な文字が無い |
東京都港区, 六本木 | "東京都港区, 六本木" | カンマを含む |
He said "hi" | "He said ""hi""" | " を含む。囲んだうえで "" に重ねる |
| 改行を含む値 | "改行(改行)あり" | 改行を含む。\n にはしない |
| 先頭に空白がある値 | " 前に空白"(記事内ツール) | 読み込む側で空白が消されないように囲む |
CSV に \ のエスケープはありません。\" と書いた CSV は、RFC 4180 の形として読むと列がずれます。記事内ツールの CSV は、先頭か末尾に空白がある値も " で囲みます。Python での CSV の読み書きと文字化けの対策は、関連記事「PythonでCSVを読み書き|コピペ用テンプレートと文字化け対策」で扱っています。
次の節では、Python・Java・PHP・シェルの文字列で、言語ごとに違うところをまとめます。
Python・Java・PHP・シェルのエスケープ(言語別)
この節では、主な言語とシェルで、文字列の中のエスケープがどう違うかを実行結果で確かめられます。
多くの言語で \ がエスケープ文字ですが、「\ を解釈しない書き方」が言語ごとに用意されています。Windows のパスや正規表現を書くときは、その書き方を使うと \ を重ねずに済みます。
| 言語 | \ を解釈する | \ を解釈しない | 注意 |
|---|---|---|---|
| Python | "…" '…' | r"…"(raw 文字列) | 知らない \d などは SyntaxWarning |
| JavaScript | "…" '…' `…` | String.raw`…` | JSON は "…" だけ |
| Java | "…" """…""" | なし(\\ と書く) | 知らない \d はコンパイルエラー |
| PHP | "…"($変数 も展開) | '…'(\' \\ だけ) | 'a\nb' は改行にならない |
| bash | "…"($ ` \ ") | '…'(何も解釈しない) | ' の中に ' は書けない |
| PowerShell | "…"(`n など) | '…' | エスケープ文字は ` |
Python:raw 文字列と SyntaxWarning
print("C:\temp\new.txt")
print(r"C:\temp\new.txt")
C: emp
ew.txt
C:\temp\new.txt
\t がタブ、\n が改行と読まれ、パスが2行に分かれました。r を付けると \ がそのまま残ります。Python 3.12 以降は、"\d+" のように意味の無い \ の組み合わせに警告が出ます。
e2.py:2: SyntaxWarning: invalid escape sequence '\d'
print(re.findall("\d+", "a12b3"))
['12', '3']
"C:\Users\…" と書いたときの unicodeescape のエラーは、関連記事「unicodeescapeエラーの直し方|Windowsのパス」で扱っています。
Java:テキストブロックとコンパイルエラー
System.out.println("\"OK\" \\ tab[\t] \u3042");
String tb = """
{"name": "It's", "path": "C:\\\\temp"}
""";
System.out.print("text block: " + tb);
"OK" \ tab[ ] あ
text block: {"name": "It's", "path": "C:\\temp"}
Java 15 以降のテキストブロック("""…""")では、" をエスケープせずに書けます。\ は解釈されるので、JSON の中の \\ を出すにはソースで \\\\ と書きます。知らない組み合わせはコンパイルエラーです。
Bad.java:1: error: illegal escape character
public class Bad { String p = "C:\temp\data"; String q = "\d+"; }
^
PHP:単一引用符と二重引用符
echo 'a\nb \' \\', "\n";
echo "a\tb \$x \"", "\n";
a\nb ' \
a b $x "
PHP の '…' で解釈されるのは \' と \\ だけで、\n は2文字のまま出ました。"…" では \t がタブに、\$ が $ になります。
bash:空白・$・引用符
name=RJC
echo "1: $name \$name \"q\" \\ \`x\`"
echo '2: $name \n "q" \'
echo 3: It\'s a pen
echo '4: It'\''s a pen'
printf '5: %q\n' "It's a pen.txt"
ls /dev/shm/t317/my file.txt
1: RJC $name "q" \ `x`
2: $name \n "q" \
3: It's a pen
4: It's a pen
5: It\'s\ a\ pen.txt
ls: cannot access '/dev/shm/t317/my': No such file or directory
ls: cannot access 'file.txt': No such file or directory
bash の '…' は何も解釈しないので、中に ' を書けません。4行目の 'It'\''s' は「'It' で閉じる → \' で ' を1つ → 's a pen' を開く」の3つをつなげた形です。空白を含むファイル名は、"…" で囲むか my\ file.txt と書かないと、2つの引数に分かれます。printf %q(bash)、Python の shlex.quote('It'"'"'s a pen.txt')、PHP の escapeshellarg('It'\''s a pen.txt')は、シェルに渡せる形を作ってくれます。
ブラウザで試す
開発者ツールのコンソール(F12)で JSON.stringify('a"b\nc') と打つと、JavaScript のエスケープ結果がその場で見られます。
ターミナルで試す
python3 -c 'import html; print(html.escape("<a & b>"))' で HTML のエスケープ結果が出ます。printf '%q\n' "It's" ならシェルの形です。
見えない文字を確かめる
printf 'a\tb\n' | od -c と打つと、\t が本当にタブ1文字になったかを \t の表示で確かめられます。
次の節では、エスケープのつまずきでいちばん多い「二重エスケープ」と「エスケープ忘れ」を見ます。
二重エスケープ(&lt;)とエスケープ忘れ
この節では、画面に < や \\ が出てしまう原因と、エスケープを何回したかの見分け方が分かります。
二重エスケープは、すでにエスケープした文字列を、もう一度エスケープしてしまうことです。画面に <b> や & のような文字参照が、そのまま見えてしまいます。A&B を Python の html.escape に繰り返し通しました。
| エスケープした回数 | HTML の文字列 | 長さ | ブラウザに見える文字 |
|---|---|---|---|
| 0回 | A&B | 3 | A&B |
| 1回(正しい) | A&B | 7 | A&B |
| 2回 | A&amp;B | 11 | A&B |
| 3回 | A&amp;amp;B | 15 | A&amp;B |
Chromium で &lt;b&gt;太字 を表示すると、画面には <b>太字 と出ました。画面に & や < が見えたら、amp; の数だけ余分にエスケープしています。JSON でも同じことが起き、C:\temp を json.dumps に繰り返し通すと \ が 1→2→4→8 個と倍に増えました。
0 C:\temp 7
1 C:\\temp 8
2 C:\\\\temp 10
3 C:\\\\\\\\temp 14
& 1つが & になる\ が倍になるensure_ascii 既定で 8→48 文字エスケープすると文字数も増えます。同じ文字列を各方式で変換した長さを測りました。
| 元の文字列 | 元 | HTML | JSON(既定) | re.escape |
|---|---|---|---|---|
| 英数字と空白(hello world 123) | 15 | 15 | 15 | 17 |
| HTML の断片(26文字) | 26 | 55 | 28 | 32 |
| Windows のパス(21文字) | 21 | 21 | 24 | 25 |
| 日本語(東京都港区六本木) | 8 | 8 | 48 | 8 |
二重エスケープが起きる典型
エスケープする場所
htmlspecialchars して DB に入れ、表示するテンプレートでも自動エスケープされる。CSV や JSON に出すと & が混ざる決まり:エスケープは「入れるとき」ではなく「出すとき」に、行き先ごとに1回
エスケープは行き先で形が変わるので、保存する時点で HTML 用にしてしまうと、JSON や CSV に出すときに合わなくなります。データは元の文字のまま持ち、出す直前に1回が、二重エスケープもエスケープ忘れも防ぐ基本です。
逆の「エスケープ忘れ」は、前の節までに見た表示崩れ(タグが消える・属性が切れる)や文法エラー(SyntaxError・syntax error at or near)として出ます。次の節で、エラーの原文をまとめて見ます。
よくあるエラー/つまずき(原文つき)
この節では、エスケープが原因で出るエラーメッセージの原文と、原因・直し方が一覧で分かります。
この記事の環境で実際に出したエラーです。エラー文で検索してきた場合は、左の列から探します。
| エラーの原文 | 出た場所 | 原因 | 直し方 |
|---|---|---|---|
SyntaxError: unterminated string literal (detected at line 1) | Python | 'It's a pen' の途中の ' で文字列が終わった | "It's a pen" か 'It\'s a pen' |
SyntaxError: Unexpected identifier 's' | Node.js | 同上(JavaScript) | "It's"・'It\'s'・テンプレートリテラル |
SyntaxWarning: invalid escape sequence '\d' | Python 3.12 以降 | "\d" は意味の無い組み合わせ | r"\d+" と raw 文字列にする |
(unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape | Python | "C:\Users" の \U が Unicode の書き方と読まれた | r"C:\Users"・/ 区切り |
error: illegal escape character | Java(javac) | "\d" "C:\temp\data" の \d | \\ と重ねる |
SyntaxError: Bad escaped character in JSON at position 13 | JSON.parse | JSON の中の \U など | \\ にする。JSON は JSON.stringify で作る |
JSONDecodeError: Invalid \escape: line 1 column 13 (char 12) | Python json.loads | 同上 | 同上(json.dumps で作る) |
re.PatternError: nothing to repeat at position 0 | Python re | 先頭の + * ? をエスケープしていない | re.escape か \+ |
Invalid regular expression: /(tax+/: Unterminated group | JavaScript | ( をエスケープしていない | \(・エスケープ関数 |
IllegalArgumentException: Illegal group reference | Java replaceAll | 置換後の文字列の $ | Matcher.quoteReplacement |
ERROR: syntax error at or near "a" | PostgreSQL | 'It's a pen' の ' を重ねていない | 'It''s a pen'・プレースホルダ |
ERROR: unterminated quoted string at or near "';" | PostgreSQL | MySQL の書き方 'It\'s' を使った | 'It''s' と重ねる |
unexpected EOF while looking for matching `'' | bash | '…' の中に ' を書いた | "It's" か 'It'\''s' |
エラーにならないつまずきもあります。こちらは画面や結果を見て気づきます。
- 1説明に書いたタグが画面から消える
<をエスケープしていない。<にする - 2画面に & や < が見える二重エスケープ。エスケープを出力の直前1回にする
- 3入力欄の値が途中で切れる属性の値の
"をエスケープしていない。"にする - 4CSV を開くと列がずれるカンマを含む値を
"で囲んでいない。CSV のライブラリで書く - 5Windows のパスが2行に分かれる
\n\tが改行・タブと読まれた。raw 文字列か/区切り - 6正規表現が何にも一致しない
$.が記号として働いている。エスケープ関数を通す
次の節では、エスケープと混同しやすい言葉との違いを整理します。
エスケープとEscキー・エンコード・サニタイズの違い
この節では、エスケープと名前や目的が近い言葉(Esc キー・URL エンコード・Base64・暗号化・サニタイズ)との違いが分かります。
Esc キーとエスケープ処理は、名前の由来(escape=抜け出す)は同じですが、別のものです。Esc キーは操作を取り消す・画面を閉じるためのキーで、文字列の書き換えとは関係ありません。キーボードの Esc キーは、押すと ESC という制御文字(ASCII の27番)を送る仕組みで、ターミナルの色の命令などに使う ESC 文字と同じ文字です。
| 言葉 | 何をするか | 元に戻せるか | 例 |
|---|---|---|---|
| エスケープ | 特別な記号を、その場所で「ただの文字」になる形に書き換える | 戻せる | < → < |
| URL エンコード | URL に書けない文字を % と16進数にする(エスケープの一種) | 戻せる | あ → %E3%81%82 |
| Base64 | バイト列全体を64種類の文字で書き直す | 戻せる | A → QQ== |
| 暗号化 | 鍵が無いと読めない形にする | 鍵があれば戻せる | TLS・ファイルの暗号化 |
| サニタイズ | 入力から不要・危険な部分を取り除く・無害化する | 取り除いた部分は戻らない | HTML から許可したタグだけ残す |
| バリデーション | 形が正しいかを確かめ、合わなければ受け付けない | 書き換えない | 郵便番号が7桁か確かめる |
URL エンコードは、URL という場所でのエスケープです。仕組みと言語ごとの関数の違いは、別の記事「URLエンコード・デコード変換ツール|%E3%81%82の読み方と言語別の違い」で扱っています。エスケープは「意味を変えずに、置き場所に合う形にする」もので、内容を隠す(暗号化)ものでも、内容を減らす(サニタイズ)ものでもありません。
次の節では、ここまでの内容を「どれを使うか」の判断表にまとめます。
どのエスケープを使うかの判断表
この節では、文字列の行き先から、使うエスケープと関数を選べます。
エスケープの方式は、文字列の中身ではなく「どこに入れるか」で決まります。上から順に当てはめます。
- 1アプリから SQL に値を渡す → プレースホルダ自分で
''にしない。?:name$1 - 2画面(HTML)に出す → テンプレートの自動エスケープ・textContent手で書くなら html.escape・htmlspecialchars で5文字
- 3JSON を作る → JSON.stringify・json.dumps文字列の連結で組み立てない
- 4CSV を作る → csv モジュール・fputcsvカンマ・"・改行のときだけ " で囲む
- 5入力から正規表現を作る → re.escape・RegExp.escape・Pattern.quote置換後の文字列は quoteReplacement・関数で返す
- 6シェルのコマンドに渡す → 引数の配列で渡す文字列で組むなら shlex.quote・escapeshellarg
- 7ソースコードに直接書く → 引用符を選ぶ・raw 文字列
"It's"・r"C:\temp"・テキストブロック
| 状況 | 使うもの | 避けたい書き方 |
|---|---|---|
| ブログに HTML のコード例を載せる | < > & に書き換える(記事内ツール) | < をそのまま貼る |
| 利用者の入力を画面に出す | テンプレートの自動エスケープ | innerHTML に文字列を連結して入れる |
| ログに日本語の JSON を出す | ensure_ascii=False・JSON_UNESCAPED_UNICODE | JSON を文字列で組み立てる |
| SQL を手で書いて実行する | '' で重ねる | MySQL だけで通る \' に頼る |
| Excel で開く CSV を出す | CSV のライブラリ | , で join するだけ |
| Windows のパスを書く | r"…"・String.raw・/ 区切り | "C:\temp\new" |
| エスケープ済みの文字列を受け取った | 1回だけ元に戻す(ツールの「元に戻す」) | 戻さずに、さらにエスケープする |
よくある質問(エスケープの意味と書き方)
この節では、エスケープについてよく聞かれる疑問への短い答えが分かります。
Q. エスケープとエスケープ文字は同じですか?
エスケープは「記号をただの文字として扱わせる書き換え」という処理、エスケープ文字は、その目印に使う文字(\ や &)です。
Q. エスケープシーケンスとは何ですか?\n(改行)や \t(タブ)のように、エスケープ文字と普通の文字を組み合わせて、1つの文字や命令を表す並びです。
Q. エスケープと Esc キーは関係ありますか?
名前の由来(escape=抜け出す)は同じですが、用途は別です。Esc キーは操作の取り消し、エスケープ処理は文字列の書き換えです。
Q. HTML では何文字をエスケープすればよいですか?
本文だけなら & < > の3文字、属性の値にも使うなら " ' を加えた5文字です。迷ったら5文字にします。
Q. < と表示されてしまいます。
二重エスケープです。エスケープ済みの文字列を、もう一度エスケープしています。保存するときにはエスケープせず、出力の直前に1回だけにします。
Q. バックスラッシュ(\)と円記号(¥)は同じですか?
日本語の Windows の一部のフォントでは、\ が ¥ の形で表示されます。文字コードは同じ(0x5C)で、エスケープ文字として同じように働きます。
Q. JSON で日本語が \u3042 のようになります。
Python の json.dumps と PHP の json_encode の既定の動きで、JSON として正しい形です。読み込めば元に戻ります。日本語のまま出すなら ensure_ascii=False・JSON_UNESCAPED_UNICODE を指定します。
Q. SQL の ' は \' と '' のどちらで書きますか?'' です。標準の書き方で、PostgreSQL・MySQL・SQLite などのどれでも通ります。\' は MySQL の既定では通りますが、PostgreSQL のふつうの文字列では通りません。
Q. エスケープすればアプリの値の受け渡しはそれだけでよいですか?
SQL はプレースホルダ、HTML はフレームワークの自動エスケープを使うのが基本です。手でのエスケープは、SQL や HTML を直接書くときに使います。
Q. CSV のエスケープは \" ですか?
いいえ。RFC 4180 の CSV では、値を " で囲み、中の " を "" に重ねます。\ は使いません。
Q. ツールに貼った内容は送信されますか?
送信されません。変換はこの端末のブラウザの中だけで行います。
まとめ
- エスケープとは、文字列の中で特別な意味を持つ記号を、ただの文字として扱わせるために決まった形へ書き換えること。目印の文字そのものも重ねて書く。
- 書き方は行き先で決まる。HTML は
&<>"'、JavaScript・JSON は\"\n、正規表現は\.\$、SQL は''、CSV は"…"と""。 - 手で置き換えず、html.escape・JSON.stringify・re.escape・csv モジュールなどの関数に任せる。アプリの値はプレースホルダとテンプレートの自動エスケープを使う。
- 画面に
&lt;が見えたら二重エスケープ。データは元の文字のまま持ち、出力の直前に行き先に合わせて1回だけエスケープする。 \を解釈しない書き方(Python の raw 文字列・String.raw・bash の'…')を使うと、Windows のパスや正規表現が読みやすくなる。
参考・出典
確認日はいずれも 2026年11月9日 です。
- WHATWG「HTML Standard」13.5 Named character references:https://html.spec.whatwg.org/multipage/named-characters.html
- MDN「Character reference(文字参照)」:https://developer.mozilla.org/en-US/docs/Glossary/Character_reference
- MDN「RegExp.escape()」:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/escape
- MDN「正規表現」(エスケープ):https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_expressions
- MDN「文字列」(エスケープシーケンス):https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String
- IETF「RFC 8259 The JavaScript Object Notation (JSON) Data Interchange Format」7. Strings:https://www.rfc-editor.org/rfc/rfc8259#section-7
- IETF「RFC 4180 Common Format and MIME Type for Comma-Separated Values (CSV) Files」:https://www.rfc-editor.org/rfc/rfc4180
- Python ドキュメント「html --- HyperText Markup Language のサポート」:https://docs.python.org/ja/3/library/html.html
- Python ドキュメント「re --- 正規表現操作」re.escape:https://docs.python.org/ja/3/library/re.html
- Python ドキュメント「字句解析」文字列およびバイト列リテラル:https://docs.python.org/ja/3/reference/lexical_analysis.html
- PHP マニュアル「htmlspecialchars」:https://www.php.net/manual/ja/function.htmlspecialchars.php
- Oracle「The Java Language Specification, Java SE 21」3.10.7 Escape Sequences:https://docs.oracle.com/javase/specs/jls/se21/html/jls-3.html
- PostgreSQL 16 文書「4.1. 字句構造」文字列定数:https://www.postgresql.org/docs/16/sql-syntax-lexical.html
- MySQL 8.4 Reference Manual「11.1.1 String Literals」:https://dev.mysql.com/doc/refman/8.4/en/string-literals.html
- GNU「Bash Reference Manual」3.1.2 Quoting:https://www.gnu.org/software/bash/manual/bash.html#Quoting
- Microsoft Learn「about_Special_Characters」(PowerShell):https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_special_characters
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「エスケープとは?意味とHTML・JS・正規表現・SQL・CSVの書き方(変換ツール)」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。