【Java】エスケープシーケンス一覧表

Javaのエスケープシーケンスを一覧表にまとめています。

一部は詳しい解説も行っています。辞書的にお使いください。

一覧表はこちらからご覧になれます。

記事内のコードは OpenJDK 21 で動作確認済みです。

エスケープシーケンスとは

Javaのエスケープシーケンス(エスケープ文字)とは、制御文字や特別な記号、あるいは文字コード単位で指定したい文字を表記するための、\(バックスラッシュ)から始まる特殊記法のことです。Javaでは12種類が用意されています。

使用できるのは文字列リテラル・文字リテラル・テキストブロックです(例外あり)。

\(バックスラッシュ)は環境によっては ¥(円記号)として表示されますが、内部的には同一文字として扱われています。

エスケープシーケンスは制御系・文字系・数値系整形系の4種類に大別でき、それぞれ以下のような特徴を持ちます。

制御系

改行( LF )や水平タブ( HT )など、直接入力しにくい制御文字を表すためのエスケープシーケンスです。

各エスケープシーケンスは一つの制御文字に対応し、文字の位置や改行など、表示時の動作を制御します。

制御文字についてはこちらの記事で分かりやすく解説されています。

文字系

構文上特別な意味を持つ文字"' など)を、通常の文字として扱うためのエスケープシーケンスです。これをエスケープ処理ともいいます。

例えば、" は文字列リテラルの開始・終了を示す特別な文字ですが、 \" のようにエスケープすることで、リテラル中に " を通常の文字として含めることができます。

数値系

文字を文字コード(数値)で指定するためのエスケープシーケンスです。

Javaの数値系エスケープシーケンスは Unicode(UTF-16)に基づいています。

例えば、「あ」は Unicodeコードポイントで U+3042 であるため、\u3042 と記述すると「あ」を表現できます。

整形系

(主に)テキストブロックで使用し、生成する文字列の整形を行うためのエスケープシーケンスです。

ブロック内の改行を無視したり、スペース文字を明示的に記述(保持)したりすることができます。

エスケープシーケンスの中ではややトリッキーです。

一覧表

リンクをクリックすると解説に飛びます。

解説は順次更新予定です。

エスケープシーケンス意味種類備考
\bBS バックスペース制御系ほぼ使われない
\fFF 改ページ制御系全く使われない
\nLF 改行制御系出力時の不整合に注意
\rCR 復帰制御系ほぼ使われない
\tHT 水平タブ制御系固定幅ではない
\\\ (バックスラッシュ)文字系
\'' (引用符)文字系
\"" (二重引用符)文字系
\XXX8進定数( XXX は 0~377 の8進数)数値系実質的にLatin-1文字コード
\uXXXX16進定数( XXXX は4桁の16進数)数値系※1Unicode(UTF-16)文字コード
\sスペース(の保持)整形系※2Java 15 以降
\<LineTerminator>行継続整形系※3Java 15 以降

※1 文字(列)リテラル外でも使用でき、字句解析前に文字へ変換される
※2 仕様上は半角スペースを表す文字系エスケープシーケンスだが、実用上は行末スペースの保持用途で使われることが多いため、整形系に含めている
※3 <LineTerminator> はソースコード上の改行を示す

よく利用されるのは \n \t \\ \' \" です。

制御系

\b – バックスペース

\bバックスペース(Back Space BS )を挿入するエスケープシーケンスです。

主な動作には2通りあり、どちらになるかは環境によって異なります。

多くの環境では前者となります。

1文字消去する

文字を1文字だけ消去し、カーソルもそれに従って1文字分戻ります。キーボードの BackSpace キーと同じです。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("ABCDE\b");
    }
}
実行結果
ABCD

E が消去されているのが確認できます。


\b の後ろに文字が続く場合は、次のようになります。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("ABC\bDE");
    }
}
実行結果
ABDE

C が消去され、B に続けて文字が入力されているのが確認できます。

カーソルを1文字分だけ戻す

文字の消去は行わず、カーソルを1文字分だけ戻します。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("ABCDE\b");
    }
}
実行結果
ABCDE

実行結果に変化はありませんが、内部的にはカーソルが戻った状態になっています。続けて文字を表示すると次のようになります。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("ABCDE\b");
        System.out.print("Hello"); // 続けて文字を表示
    }
}
実行結果
ABCDHello

カーソルは DE の間に移動した状態です。続けて文字を表示すると EHello上書きされ、表示されません。


ここでは代表的な2通りの動作を紹介しましたが、実際にはこれ以外の動作も多く、\b が文字として可視化されたり、(豆腐)として表示されたり、あるいは完全に無視されたりする場合もあります。

動作が安定しないため、現代ではほとんど使われません。

\b は「表示の制御」しかしない

1つ目・2つ目の例ともに、E は完全に削除されたように見えます。

しかし、\b はあくまで表示を制御するだけで、実際のデータを削除する機能は持ちません。

例えば、ABC\bD\bE と記述した場合、表示上は ABE に見えますが、データとしては ABC\bD\bE がそのまま保持されます。そのため、この状態で文字列を構文解析やファイル出力に通すと、予期せぬ動作を引き起こす可能性があります。

\b の存在意義

\bBS )は文字を疑似的に消去するために誕生しました。

初期のテレタイプ端末(TTY)では、一度入力した文字は即座に紙や画面に反映され、「文字を消去する」という概念自体が存在しませんでした。

そこで、カーソルを1文字分戻し、スペースを上書き入力することで消去したように見せる方法が用いられました。この「1文字分戻す」操作を担っていたのが \b です。

今日では文字の編集は簡単に行えるため、\b はほとんど使用されなくなりました。ただし、一部のターミナルアプリでは、今でも見かける機会があります。

\f – 改ページ

\f改ページ(Form Feed FF )を挿入するエスケープシーケンスです。

このエスケープシーケンスは現代ではほとんど機能しません。文字として可視化されたり、(豆腐)として表示されたり、あるいは完全に無視されます。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("1ページ目\f2ページ目");
    }
}
実行結果(環境により異なる)
1ページ目□2ページ目

現代では全くと言っていいほど使われません。

\f の存在意義

\fFF )は本来、プリンタ制御のための制御文字です。

初期のプリンタは、コンピュータから送られてくる文字列(文字ストリーム)をそのまま解釈し、順に印字する仕組みでした。

\f を受け取ると、用紙を送って改ページを行い、次のページの先頭から印字を開始します。

現代では、印刷はページ記述言語やレイアウトエンジンによって制御されます。そのため、上記で紹介したような原始的な方法はほぼ見られません。

\f は物理的な印刷制御が主流だった時代の、歴史的な名残りと言えるでしょう。

\n – 改行

\n改行(Line Feed LF )を挿入するエスケープシーケンスです。

数あるエスケープシーケンスの中でも特に使用頻度が高く、さまざまな場面で登場します。

基本的な動作は次のようになります。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("1行目\n");
        System.out.print("2行目");
    }
}
実行結果
1行目
2行目

「1行目」の後に改行され、「2行目」が次の行に表示されているのが確認できます。


文字列の途中に \n を記述した場合は次のようになります。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("私は\n今日\n学校に\n行きました");
    }
}
実行結果
私は
今日
学校に
行きました

複数回連続で \n を記述した場合は次のようになります。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("1行目\n\n\n");
        System.out.print("4行目");
    }
}
実行結果
1行目


4行目

文字(列)リテラルに組み込める特徴を活かし、次のような使い方もできます。

コード
public class Main {
    public static void main(String[] args) {
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j < 10; j++) {
                System.out.print((i * j) + (j == 9 ? "\n" : "\t"));
            }
        }
    }
}
実行結果
1	2	3	4	5	6	7	8	9
2	4	6	8	10	12	14	16	18
3	6	9	12	15	18	21	24	27
4	8	12	16	20	24	28	32	36
5	10	15	20	25	30	35	40	45
6	12	18	24	30	36	42	48	54
7	14	21	28	35	42	49	56	63
8	16	24	32	40	48	56	64	72
9	18	27	36	45	54	63	72	81

三項演算子を利用し、j == 9 の場合のみ改行するようにしています。if - else 文および System.out.println() でも同じことはできますが、こちらはより簡潔です。


使いどころ

  • 簡易的な改行
  • 簡易的なコンソール(ログ)出力
  • 簡易的なファイル出力

※ なぜ「簡易的」なのかは次項以降で解説しています。


System.lineSeparator()%n

改行を行うものとして、\n のほかに System.lineSeparator()System.out.printf()String.format() で利用可能な %n があります。

どちらも「改行する」点では同じですが、その環境互換性に差があります。詳しい説明は省略しますが、\n よりも lineSeparator()%n の方が環境互換性は高いです。

ただし、現代の多くの環境では \n も問題なく扱えるため、通常は \n で問題ありません。

それでも、環境によっては不整合が生じることもあります。詳しくは【発展】OSごとの改行コードと \n(LF)の不整合をご覧ください。

【発展】\n(LF)の本来の動作と改行の関係

本項では、\n の実体である LF を対象とします。そのため、コード内以外の表記は LF に統一し、呼称も「エスケープシーケンス」ではなく「制御文字」とします。

CR\r )も扱います。

ここまで、LF は改行を挿入するための制御文字だと説明してきました。

しかし、これは実用的な説明であり、理論上は誤りです。

本来、LF は「1行分の行送りを行う(カーソルを1行分下にずらす)」ことを意味する制御文字です。そのため、正確には次のような動作を取るべきものです。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("1行目\n");
        System.out.print("2行目");
    }
}
実行結果(理論上)
1行目
     2行目

理論上、新たな行は行頭からではなく、行送りによってカーソルが配置された場所から開始されます。行送りだけではカーソルを行頭に戻すことはできず、 LF だけでは行頭からの改行は成立しません。

したがって、改行を行うためには、行送り( LF )に加え、行頭復帰( CRを行う必要があります。

行頭復帰とは、カーソルを行頭に戻す操作のことです。縦方向は移動せず、横方向の位置のみを変更します。

コード
public class Main {
    public static void main(String[] args) {
        System.out.print("1行目\r\n");
        System.out.print("2行目");
    }
}
実行結果
1行目
2行目

両者をまとめて CRLF と表します。

改行に必要な制御文字を改行コードと呼びます。


ここまで説明した通り、CRLF が理論上正しい改行コードです。しかし、コンピュータの発展と共に、この扱いはOSごとに分岐していきます。

CRLFの起源

CRLF の起源は、タイプライターにあります。

タイプライターとは、キーボードによく似た文字盤を打鍵して、用紙に直接文字を打ち込むための道具です。まさに現代のキーボードの「祖先」と言える存在です。

タイプライター(引用:Wikipedia

タイプライターでは、改行は一つの動作ではありませんでした。

  • CR(キャリッジリターン):文字を打つ位置(キャリッジ)を行頭に戻す
  • LF(ラインフィード):用紙を1行分送り出す(行送り)

この2つを組み合わせて初めて、改行が実現できたのです。

この仕組みはのちにテレタイプ端末(TTY)に受け継がれ、さらにコンピュータへと引き継がれていきました。

【発展】OSごとの改行コードと \n(LF)の不整合

本項を読む前に前項を読むことをお勧めします。

前項で説明した通り、理論上正しい改行コードは CRLF です。しかし、現代では、OSごとに異なる改行コードが採用されています。代表例を以下に示します。

  • Windows: CRLF
  • UNIX / Linux / macOS: LF
  • Classic Mac OS(2000年代前半までサポートされていたMacのOS): CR

Javaの \nLF を表します。改行命令として扱う場合、LinuxやmacOSでは改行コードとして LF が採用されているため、そのまま使用しても問題ありません。

Windowsでは改行コードとして CRLF が採用されていますが、ターミナルやコンソールに出力(表示)する場合は、通常 \n だけでも改行として認識されます。しかし、\n を含む文字列をファイルとして保存する場合は、不整合が発生しやすくなります。

特に、CRLF を前提とするWindows系ツールや文字列処理プログラムが、期待通りに動作しないことがあります。

かつては、エディタで開いた際に LF 単体の改行が正しく解釈されず、改行されずに表示されることがありましたが、最近はこうした問題はほとんど見られません。

こうした問題を回避するためには、明示的に \r\n を記述するか、OSに合わせた改行コードを出力してくれる System.lineSeparator()%n を使用します。ただし、\r\n はWindows固定になってしまうため、System.lineSeparator() %n の方が良いでしょう。

コード
import java.nio.file.*;
import static java.nio.file.StandardOpenOption.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // test.txt に文字列を保存

        // System.lineSeparator() を使用
        Files.writeString(
                Path.of("test.txt"),
                "Hello" + System.lineSeparator()
                        + "Java" + System.lineSeparator(),
                APPEND, CREATE
        );

        // %n を使用
        Files.writeString(
                Path.of("test.txt"),
                "Hello%nJava%n".formatted(),
                APPEND, CREATE
        );
    }
}
実行結果
Hello
Java
Hello
Java

OS改行コードの歴史的背景

現在の改行コードの違いは、各OSが歩んできた歴史的背景と設計思想の差を反映しています。以下にその概要をまとめます。

WindowsはCP/MMS-DOSの流れを強く引き継いでいます。CP/Mはテレタイプ端末(TTY)前提のOSであり、TTYでは CRLF が改行の基本操作となっていました。当時は物理モデルと論理モデルがあまり分離されておらず、CRLF は自然に改行コードとして取り込まれました。

時代が進み、TTYは使われなくなり、 CRLF も必須ではなくなりました。しかし、Windowsは後方互換性を重視していたため、CRLF はそのまま残り、それが現代まで引き継がれています。

UNIXはもともと、大学発の実験的なプロジェクトでした。物理モデルと論理モデルを切り離す方向に進み、OSは抽象的な概念(ストリームやパイプなど)を基本として設計されました。

その過程で、改行を「行送りと行頭復帰の物理命令」ではなく、「行の終端マーカー」として扱う発想が生まれました。改行コードは LF のみとし、必要であれば端末側で CR を補うという設計が取られたのです。

Linuxも、UNIXの設計思想を受け継ぎ LF を採用しました。macOSは、Classic Mac OSから移行するにあたりUNIX系の基盤を採用したため、それに伴って改行コードも LF に統一されました。

Macは初代からGUIが中心の設計でした。TTYの流れを引き継いでいるわけでもなく、かといってUNIX文化圏に属しているわけでもない、独立した立ち位置でした。

当時のMacでは、改行キーは Enter キーではなく、Return キーという名称でした。改行を実装するにあたり、何かしら改行コードを設定する必要がありましたが、この Return キーと名称が近かったのが CR(Carriage Return)です。

対応関係も自然であり、扱いやすい選択肢だったと考えられます。

\t – 水平タブ

\t水平タブ(Horizontal Tab HT )を挿入するエスケープシーケンスです。

次のタブストップまでカーソルを移動させます。

タブストップとは、HT\t )が入力された際にカーソルが移動する、行内の決まった位置(区切り)のことです。

また、タブストップ間の幅のことをタブ幅といいます。タブ幅は表示環境によって異なりますが、4カラムまたは8カラムが主流です。

カラムとは、テキストの表示上の横方向位置を表す単位です。カラム幅は表示環境によってさまざまな定義方法があります。

特に断りがない限り、本記事ではタブ幅を4カラムとし、1カラムは半角英数字1文字分の横幅とします。


\t は固定長の半角スペースを挿入するエスケープシーケンスだと誤解されがちですが、実際に表示される空白幅はカーソルの現在位置によって変化します。

また、表示される空白も、半角スペースの並びではなく、\tHT )という一文字として扱われます。


基本的な動作は次のようになります。

コード
public class Main {
    public static void main(String[] args) {
        System.out.println("Name\tPrice\tAmount");
    }
}
実行結果
Name	Price	Amount

空白が固定幅ではないことが確認できます。


「次のタブストップまで移動」という特徴を活かし、複数行にわたる文字列表示を位置揃え(整形)することもできます。

コード
public class Main {
    public static void main(String[] args) {
        System.out.println("Name\tPrice\tAmount");
        System.out.println("Apple\t2000\t50");
    }
}
実行結果
Name	Price	Amount
Apple	2000	50

各要素の左端が位置揃えされ、表のような見た目となります。


ただし、要素幅の差が大きすぎたり、英数字以外が含まれている場合は、正しく位置揃えできないことがあります。

コード
public class Main {
    public static void main(String[] args) {
        System.out.println("Name\tPrice\tAmount");
        System.out.println("Blueberry\t6500\t100");
        System.out.println("バナナ\t10000\t1000");
    }
}
実行結果
Name	Price	Amount
Blueberry	6500	100
バナナ	10000	1000

この場合、\t を増やす・手動でスペースを挿入するなどの対応が必要になります。


使いどころ

  • 簡易的な位置揃え(ログやデバッグにおける表形式表示など)
  • 区切り文字として使用(TSVファイルなど)

\t を使えば手軽に位置揃えできますが、表示環境やタブ幅の設定に依存するため、柔軟性はあまり高くありません。より厳密な位置揃えを行いたい場合は、書式指定文字列をサポートする System.out.printf()String.format() を使用すると良いでしょう。


Tab キー入力の自動変換に注意

Tab キーは \t と同じく、水平タブ( HT )を入力するためのキーです。

そのため、エディタ内で Tab を入力すると、本来はそのまま水平タブが挿入されます。

しかし、IDE(統合開発環境)や一部の高機能なエディタは、Tab 入力を自動的に半角スペース4つに変換することがあります。

プログラミングでは、Tab キーは主にインデント挿入のために使用されます。インデント自体はスペースでも水平タブでも問題ありませんが、HT の表示幅は環境ごとに異なるため、表示が崩れる可能性があります。そのため、多くの開発環境では、水平タブを半角スペースに変換する設定が採用されています。

なお、Javaの公式スタイルガイドでも、インデントは半角スペース4つとすることが推奨されています。

HT Tab キーの関係

Tab キーには、↹ のような記号が印字されている場合があります。

キーボードのTabキー(引用:FreeImages.com / OmirOnia)

この記号はまさに、「次のタブストップ( | )までカーソルを移動させる( ⇆ )」ことを表しています。

関連記事