結論

エスケープとは、文字列の中で「区切り」や「命令」として特別な意味を持つ記号を、ただの文字として扱えるように決まった形へ書き換えることです。HTML では < を &lt; に、JavaScript の文字列では " を \" に、SQL の文字列では ' を '' に書き換えます。どの書き方になるかは、文字列を「どこに入れるか」で決まります。

この記事でわかること

  • エスケープの意味(ふだんの「逃げる」との関係)と、エスケープ文字・エスケープシーケンス・Esc キーの違い
  • HTML・JavaScript/JSON・正規表現・SQL・CSV・Python・Java・PHP・シェルの書き方を、実際に動かした出力つきで
  • 二重エスケープ(&amp;lt;)やエスケープ忘れで出るエラーの原文と、行き先から選ぶ判断表

2026年11月10日更新|Python 3.13・Node.js 22・Java 21・PHP 8.3・PostgreSQL 16・bash 5.2・Chromium 153で実行確認

エスケープ変換を読み込み中です。

ツールの使い方:入力欄に文字列を貼ると、その場で結果が出ます。

  • 向きを選ぶ:「エスケープする」と「元に戻す(アンエスケープ)」を切り替えます。
  • 種類を選ぶ:HTML・JavaScript/JSON の文字列・正規表現・SQL の文字列・CSV の1項目の5種類です。
  • HTML:& < > の3文字だけにするか、" ' も含めた5文字にするかを「" と ' も変換する」で選べます。エスケープした結果の下に、ブラウザでの見え方(タグとしては動かず、文字として表示)も出ます。元に戻すときは &lt; &copy; などよく使う約40個の名前つき文字参照と、&#12354;・&#x3042; の数値の形に対応し、知らない名前はそのまま残して個数を示します。
  • JavaScript/JSON:" \ 改行・タブなどを \ 付きの形にします。元に戻すときは \n \t \" \\ \u3042 \x41 などを文字に戻し、\u の後ろが16進数4桁でないときは何文字目かを示します。
  • 正規表現は記号の前に \ を付け、SQL は ' を '' に重ねて全体を ' で囲み、CSV は RFC 4180 の形(カンマ・"・改行を含むときだけ " で囲み、中の " を "" に)にします。
  • 結果は「コピー」ボタンでコピーできます。見本ボタン(HTML のタグ・&lt; を戻す・改行と " を含む文字・正規表現の記号・SQL の '・CSV のカンマ)で、よくある入力を試せます。入力した内容はこの端末の中だけで変換し、どこにも送信しません。

この記事で実際に動かしたもの:上のツール(Chromium で表示して20通りの入力を確認)、Python・Node.js・Java・PHP の標準の関数、127.0.0.1 に立てた PostgreSQL 16 と SQLite、bash、Chromium での HTML の表示。

よく調べられることの答えを先にまとめます。

知りたいこと 答え 詳しい節
エスケープの意味特別な意味の記号を「ただの文字」に書き換えることエスケープとは
エスケープ文字とは書き換えの目印になる文字。\・&・'(SQL)などエスケープ文字の一覧表
HTML のエスケープ& < > " ' を &amp; &lt; &gt; &quot; &#39; にHTMLのエスケープ
文字列の中に " や改行を書きたい\" \n。JSON は JSON.stringify・json.dumps に任せるJavaScript・JSONのエスケープ
正規表現で . や $ を文字として探す\. \$。re.escape・Pattern.quote・preg_quote正規表現のエスケープ
SQL で ' を含む文字列'It''s' のように重ねる。アプリはプレースホルダSQLのエスケープ
CSV でカンマを含む値"東京都港区, 六本木" と " で囲むCSVのエスケープ
&lt; と表示されてしまう二重エスケープ。エスケープを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・プログラミングでの意味
エスケープ逃げる・脱出する(脱出ゲーム、エスケープルーム)記号を特別な役目から外し、ただの文字として扱わせること
何から逃げるか部屋・危険・束縛「文字列の終わり」「タグの始まり」「何にでも一致」などの役目
身近な例非常口から外へ出る< を &lt; と書くと、タグにならず < と表示される

同じ「エスケープ」でも、場面によって指すものが違います。検索してたどり着いた場面と照らし合わせると迷いません。

場面 エスケープが指すもの 例
文字列・HTML・SQL を書くとき特別な記号をただの文字にする書き換え(この記事の主題)&lt; \" ''
文字列の中の改行やタブ見えない文字を目印付きで書く「エスケープシーケンス」\n(改行) \t(タブ)
キーボード操作を取り消す・閉じる Esc キーダイアログを閉じる、Vim で入力を抜ける
ターミナルの色や位置の指定ESC 文字(制御文字の27番)から始まる命令の並び文字に色を付ける命令
Java などの最適化「エスケープ解析」。オブジェクトがメソッドの外へ出ていくかの解析JVM の JIT コンパイラの最適化

1エスケープ(処理)

記号を書き換える行為そのもの。「HTML エスケープする」「エスケープ漏れ」のように使います。

2エスケープ文字

書き換えの目印になる文字。多くの言語では \(バックスラッシュ)、HTML では &、SQL では引用符そのもの。

3アンエスケープ

エスケープした形を元の文字に戻すこと。デコード、アンエスケープ、エスケープ解除とも呼びます。

次の節では、なぜこうした書き換えが必要になるのかを、2つの役割に分けて見ます。

エスケープが必要になる理由(区切りと中身がぶつかる)

この節では、エスケープが必要になる仕組みと、エスケープの2つの役割が分かります。

エスケープが必要になるのは、「区切りや命令に使う記号」と「中身として書きたい文字」が同じ記号だからです。HTML は < でタグの始まりを、JavaScript は " で文字列の端を、CSV は , で項目の区切りを表します。中身にも同じ記号を書きたいとき、プログラムはどちらの意味か区別できません。そこで「中身のほうは別の形で書く」と決めておくのがエスケープです。

役割1:意味を打ち消す

\" … 文字列の終わりではなく、ただの "

&lt; … タグの始まりではなく、ただの <

\. … 正規表現の「任意の1文字」ではなく、ただの .

役割2:意味を足す

\n … ただの n ではなく、改行

\t … ただの t ではなく、タブ

\u3042 … 文字コード U+3042 の「あ」

役割2のように、キーボードで打ちにくい文字や見えない文字(改行・タブ・NUL など)を、目印と普通の文字の組み合わせで書く形をエスケープシーケンスと呼びます。どちらの役割でも、「目印の文字」が先頭に付く点は同じです。

目印の文字そのものを書きたいときは、目印を2つ重ねます。\ を1つ書きたいときは \\、HTML で & を書きたいときは &amp;、SQL で ' を書きたいときは '' です。「目印そのものもエスケープする」は、どの場所にも共通する決まりで、ここを忘れると次の節以降で見るエラーや表示崩れが起きます。

続いて、場所ごとのエスケープ文字を一覧表で見ます。

エスケープ文字の一覧表(場所別)

この節では、HTML・JavaScript・正規表現・SQL・CSV・シェルで、どの文字がエスケープ文字になり、何をどう書き換えるかが分かります。

エスケープ文字は場所ごとに違います。同じ ' でも、JavaScript なら \'、SQL なら ''、HTML の属性なら &#39; です。下の表の「書き換えた形」は、この記事の各節で実際に動かして確かめたものです。

場所 エスケープ文字 書き換える主な文字 書き換えた形
HTML の本文&(文字参照)& < >&amp; &lt; &gt;
HTML の属性の値&上の3つ + " '&quot; &#39;(&#x27;)
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文字を、文字参照(&amp; &lt; &gt; &quot; &#39;)に書き換えます。本文に入れるだけなら & < > の3文字、属性の値("…" の中)に入れるなら " ' も書き換えます。どちらにも使えるように、いつも5文字を書き換えるのがいちばん簡単です。

文字 文字参照(名前) 文字参照(番号) 書き換える理由
&&amp;&#38;文字参照の始まりの目印だから。いちばん先に書き換える
<&lt;&#60;タグの始まりと読まれる
>&gt;&#62;タグの終わり。本文では必須ではないが、そろえて書き換える
"&quot;&#34;属性の値を " で囲んでいると、そこで値が終わる
'&apos;&#39;属性の値を ' で囲んでいると、そこで値が終わる

エスケープしないとどう表示されるか(Chromium で確かめた結果)

同じ文章を、エスケープせずに書いた場合とエスケープした場合で、Chromium 153 に表示させ、画面に出る文字(textContent)と、できた要素の数を読み取りました。

<p>タグの例:<b>太字</b>と書きます</p>
<p>タグの例:&lt;b&gt;太字&lt;/b&gt;と書きます</p>
<p>if (a<b) { x = 1 }</p>
<p>?q=A&B&copy=1</p>
<input value="彼は "OK" と言った">
<input value="彼は &quot;OK&quot; と言った">
書いた HTML 画面に出た文字 起きたこと
<b>太字</b>(エスケープなし)タグの例:太字と書きます<b> がタグとして働き、説明したい <b> が消えた(子要素1個)
&lt;b&gt;太字&lt;/b&gt;タグの例:太字と書きます狙いどおり文字として表示(子要素0個)
if (a<b) { x = 1 }if (a<b からがタグと読まれ、後ろが太字の要素になって消えた
?q=A&B&copy=1?q=A&B©=1&copy が「©」と読まれ、URL が変わった
value="彼は "OK" と言った"彼は (ここで切れる)値は「彼は 」だけ。OK" などは別の属性名になった
value="彼は &quot;OK&quot; と言った"彼は "OK" と言った正しく表示

3行目と4行目は見落としやすい例です。a<b のように < のすぐ後ろが英字だとタグと読まれ、1 < 2 のように後ろが空白なら文字のまま残りました。また、URL の &copy=1 のようにセミコロンが無くても &copy は「©」と読まれます(HTML の仕様で、以前からある一部の名前は ; 無しでも認められています)。HTML の中に URL を書くときも & は &amp; にします。

言語・ライブラリの 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("&lt;p&gt;&amp;copy; &copy; &#12354; &#x3042; &amp;lt;"))
&lt;a href=&quot;/search?q=A&amp;B&quot;&gt;&quot;C++&quot; &amp; &#x27;Java&#x27;&lt;/a&gt;
&lt;a href="/search?q=A&amp;B"&gt;"C++" &amp; 'Java'&lt;/a&gt;
<p>&copy; © あ あ &lt;
<?php
echo htmlspecialchars($s), "\n";
echo htmlspecialchars($s, ENT_NOQUOTES), "\n";
echo htmlspecialchars("&lt; &amp;"), " | ", htmlspecialchars("&lt; &amp;", ENT_QUOTES, 'UTF-8', false), "\n";
&lt;a href=&quot;/search?q=A&amp;B&quot;&gt;&quot;C++&quot; &amp; &#039;Java&#039;&lt;/a&gt;
&lt;a href="/search?q=A&amp;B"&gt;"C++" &amp; 'Java'&lt;/a&gt;
&amp;lt; &amp;amp; | &lt; &amp;
  • Python の html.escape は、既定(quote=True)で ' を &#x27; にします。PHP の htmlspecialchars は &#039; でした。書き方は違っても、ブラウザで表示すると同じ ' になります。
  • PHP 8.1 から、htmlspecialchars の既定のフラグは ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 で、' も変換されます(PHP マニュアル)。
  • PHP の4番目の引数 double_encode を false にすると、すでに &lt; になっている部分は変換しません。ただし、二重エスケープの根本の直し方は「エスケープを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);
&lt;b&gt;太字&lt;/b&gt; 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)・タブ使える使える
\u3042U+3042(あ)使える使える
\u{1F600}U+1F600(😀)使える使えない(\uD83D\uDE00 と書く)
\x4116進数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+)」の結果
Pythonre.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 は undefinedMDN の関数で price: \$10\.00 \(tax\+\)
JavaPattern.quote(s)\Q$10.00\E(「$10.00」で実行)
PHPpreg_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')は、シェルに渡せる形を作ってくれます。

1

ブラウザで試す

開発者ツールのコンソール(F12)で JSON.stringify('a"b\nc') と打つと、JavaScript のエスケープ結果がその場で見られます。

Chrome・Edge・Firefox

2

ターミナルで試す

python3 -c 'import html; print(html.escape("<a & b>"))' で HTML のエスケープ結果が出ます。printf '%q\n' "It's" ならシェルの形です。

Linux・Mac

3

見えない文字を確かめる

printf 'a\tb\n' | od -c と打つと、\t が本当にタブ1文字になったかを \t の表示で確かめられます。

Linux・Mac

次の節では、エスケープのつまずきでいちばん多い「二重エスケープ」と「エスケープ忘れ」を見ます。

二重エスケープ(&amp;lt;)とエスケープ忘れ

この節では、画面に &lt; や \\ が出てしまう原因と、エスケープを何回したかの見分け方が分かります。

二重エスケープは、すでにエスケープした文字列を、もう一度エスケープしてしまうことです。画面に &lt;b&gt; や &amp; のような文字参照が、そのまま見えてしまいます。A&B を Python の html.escape に繰り返し通しました。

エスケープした回数 HTML の文字列 長さ ブラウザに見える文字
0回A&B3A&B
1回(正しい)A&amp;B7A&B
2回A&amp;amp;B11A&amp;B
3回A&amp;amp;amp;B15A&amp;amp;B

Chromium で &amp;lt;b&amp;gt;太字 を表示すると、画面には &lt;b&gt;太字 と出ました。画面に &amp; や &lt; が見えたら、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
4文字HTML で1回ごとに増える& 1つが &amp; になる
2倍JSON の \ の数1回ごとに \ が倍になる
6倍日本語8文字の JSONensure_ascii 既定で 8→48 文字

エスケープすると文字数も増えます。同じ文字列を各方式で変換した長さを測りました。

元の文字列 元 HTML JSON(既定) re.escape
英数字と空白(hello world 123)15151517
HTML の断片(26文字)26552832
Windows のパス(21文字)21212425
日本語(東京都港区六本木)88488

二重エスケープが起きる典型

エスケープする場所

やってはいけない保存するときに htmlspecialchars して DB に入れ、表示するテンプレートでも自動エスケープされる。CSV や JSON に出すと &amp; が混ざる
→
代わりにDB には元の文字のまま保存し、出力する直前に、出力先(HTML・JSON・CSV)に合わせて1回だけエスケープする

決まり:エスケープは「入れるとき」ではなく「出すとき」に、行き先ごとに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 escapePython"C:\Users" の \U が Unicode の書き方と読まれたr"C:\Users"・/ 区切り
error: illegal escape characterJava(javac)"\d" "C:\temp\data" の \d\\ と重ねる
SyntaxError: Bad escaped character in JSON at position 13JSON.parseJSON の中の \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 0Python re先頭の + * ? をエスケープしていないre.escape か \+
Invalid regular expression: /(tax+/: Unterminated groupJavaScript( をエスケープしていない\(・エスケープ関数
IllegalArgumentException: Illegal group referenceJava 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 "';"PostgreSQLMySQL の書き方 'It\'s' を使った'It''s' と重ねる
unexpected EOF while looking for matching `''bash'…' の中に ' を書いた"It's" か 'It'\''s'

エラーにならないつまずきもあります。こちらは画面や結果を見て気づきます。

  • 1説明に書いたタグが画面から消える< をエスケープしていない。&lt; にする
  • 2画面に &amp; や &lt; が見える二重エスケープ。エスケープを出力の直前1回にする
  • 3入力欄の値が途中で切れる属性の値の " をエスケープしていない。&quot; にする
  • 4CSV を開くと列がずれるカンマを含む値を " で囲んでいない。CSV のライブラリで書く
  • 5Windows のパスが2行に分かれる\n \t が改行・タブと読まれた。raw 文字列か / 区切り
  • 6正規表現が何にも一致しない$ . が記号として働いている。エスケープ関数を通す

次の節では、エスケープと混同しやすい言葉との違いを整理します。

エスケープとEscキー・エンコード・サニタイズの違い

この節では、エスケープと名前や目的が近い言葉(Esc キー・URL エンコード・Base64・暗号化・サニタイズ)との違いが分かります。

Esc キーとエスケープ処理は、名前の由来(escape=抜け出す)は同じですが、別のものです。Esc キーは操作を取り消す・画面を閉じるためのキーで、文字列の書き換えとは関係ありません。キーボードの Esc キーは、押すと ESC という制御文字(ASCII の27番)を送る仕組みで、ターミナルの色の命令などに使う ESC 文字と同じ文字です。

言葉 何をするか 元に戻せるか 例
エスケープ特別な記号を、その場所で「ただの文字」になる形に書き換える戻せる< → &lt;
URL エンコードURL に書けない文字を % と16進数にする(エスケープの一種)戻せるあ → %E3%81%82
Base64バイト列全体を64種類の文字で書き直す戻せるA → QQ==
暗号化鍵が無いと読めない形にする鍵があれば戻せるTLS・ファイルの暗号化
サニタイズ入力から不要・危険な部分を取り除く・無害化する取り除いた部分は戻らないHTML から許可したタグだけ残す
バリデーション形が正しいかを確かめ、合わなければ受け付けない書き換えない郵便番号が7桁か確かめる

URL エンコードは、URL という場所でのエスケープです。仕組みと言語ごとの関数の違いは、別の記事「URLエンコード・デコード変換ツール|%E3%81%82の読み方と言語別の違い」で扱っています。エスケープは「意味を変えずに、置き場所に合う形にする」もので、内容を隠す(暗号化)ものでも、内容を減らす(サニタイズ)ものでもありません。

次の節では、ここまでの内容を「どれを使うか」の判断表にまとめます。

どのエスケープを使うかの判断表

この節では、文字列の行き先から、使うエスケープと関数を選べます。

エスケープの方式は、文字列の中身ではなく「どこに入れるか」で決まります。上から順に当てはめます。

  1. 1アプリから SQL に値を渡す → プレースホルダ自分で '' にしない。? :name $1
  2. 2画面(HTML)に出す → テンプレートの自動エスケープ・textContent手で書くなら html.escape・htmlspecialchars で5文字
  3. 3JSON を作る → JSON.stringify・json.dumps文字列の連結で組み立てない
  4. 4CSV を作る → csv モジュール・fputcsvカンマ・"・改行のときだけ " で囲む
  5. 5入力から正規表現を作る → re.escape・RegExp.escape・Pattern.quote置換後の文字列は quoteReplacement・関数で返す
  6. 6シェルのコマンドに渡す → 引数の配列で渡す文字列で組むなら shlex.quote・escapeshellarg
  7. 7ソースコードに直接書く → 引用符を選ぶ・raw 文字列"It's"・r"C:\temp"・テキストブロック
状況 使うもの 避けたい書き方
ブログに HTML のコード例を載せる&lt; &gt; &amp; に書き換える(記事内ツール)< をそのまま貼る
利用者の入力を画面に出すテンプレートの自動エスケープinnerHTML に文字列を連結して入れる
ログに日本語の JSON を出すensure_ascii=False・JSON_UNESCAPED_UNICODEJSON を文字列で組み立てる
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. &lt; と表示されてしまいます。
二重エスケープです。エスケープ済みの文字列を、もう一度エスケープしています。保存するときにはエスケープせず、出力の直前に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 は &amp; &lt; &gt; &quot; &#39;、JavaScript・JSON は \" \n、正規表現は \. \$、SQL は ''、CSV は "…" と ""。
  • 手で置き換えず、html.escape・JSON.stringify・re.escape・csv モジュールなどの関数に任せる。アプリの値はプレースホルダとテンプレートの自動エスケープを使う。
  • 画面に &amp;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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

成長のヒミツ、 ぜんぶ丸わかり