英語: delimiter、デリミタ)は、コンピュータ言語データ通信において独立した領域の境界を特定するために入れられる文字である[1]。例えば、コンマ区切りの文字列において、コンマ (,) は各フィールドの境界を表す「フィールド区切り文字」の役割をしている。

Thumb
CSVフォーマットのテキストファイルの一部の抜粋。赤色で示したコンマがフィールド区切り文字として使用されている。

区切り文字は、データストリームで境界を指定する方法の1つである。別の方法として、各フィールドの先頭にフィールド長を記述する方法もある[2]

概要

区切り文字は以下の2種類に分けられる。

  • フィールド区切り文字・レコード区切り文字(例: コンマや改行)
  • 範囲指定区切り文字(例: 括弧やダブルクォート)

フィールド区切り文字・レコード区切り文字

フィールド区切り文字はデータフィールドを分離し、レコード区切り文字はフィールドのグループを分離する[3]

例えば、CSVファイルはコンマをフィールド間の区切り文字として、改行コードレコード間の区切り文字として使用している。

以下は、CSVファイルのフォーマットを使用した簡単なフラットファイルデータベーステーブルの例である。

fname,lname,age,salary
nancy,davolio,33,$30000
erin,borakova,28,$25250
tony,raphael,35,$28700

範囲指定区切り文字

範囲指定区切り文字は、テキストの範囲の最初と最後を示すものである[4][5]

よく使われる範囲指定区切り文字には、以下のものがある[6]

さらに見る 区切り文字, 説明 ...
区切り文字 説明
( ... ) 丸括弧LISPの構文は、主に丸括弧を使用することで判別可能である[7]
{ ... } 波括弧[8]
[ ... ] 角括弧
< ... > 山括弧[9]
" ... " ダブルクォート文字列リテラルを表すのに使われる[10]
' ... ' シングルクォート。文字リテラルを表すのに使われる[10]
<? ... ?> XML処理命令英語版を表すのに使われる[11]
/* ... */ いくつかのプログラミング言語でコメントを表すのに使われる[12]
<% ... %> いくつかのWebテンプレートで言語の境界を特定するのに使用する。これは「テンプレート区切り文字」とも呼ばれる[13]
閉じる

慣習

慣習的に、プラットフォームによって特定の区切り文字が使われる[14]。以下に、そのいくつかの例を示す。

プログラミング言語プログラミング言語の比較 (文法)英語版も参照)

さらに見る 文字列リテラル, 文の区切りまたは文末 ...
文字列リテラル文の区切りまたは文末
Pascal シングルクォートセミコロン
C言語 ダブルクォート、シングルクォートセミコロン
閉じる

フィールド区切り文字・レコード区切り文字ASCII制御文字も参照)

さらに見る フィールドの終了, レコードの終了 ...
フィールドの終了レコードの終了ファイルの終了
Unix, OS X, Amiga OS タブLF(なし)
Windows, MS-DOS, OS/2, CP/M タブCRLFControl-Z[15]
Classic Mac OS, AppleDOS, ProDOS, GS/OS タブCR(なし)
ASCII/Unicode UNIT SEPARATOR
Position 31 (U+001F)
RECORD SEPARATOR
Position 30 (U+001E)
FILE SEPARATOR
Position 28 (U+001C)
閉じる

区切り文字衝突

区切り文字衝突英語: delimiter collision)とは、テキスト中のある文字が区切り文字として解析され、意図しない動作を引き起こす問題である[3][16]。例えばCSVファイルの場合、フィールドにコンマを含む値(例: 38,915円87銭)を入れようとするとフィールド区切り文字衝突が起こり、複数行の値を入れようとするとレコード区切り文字衝突が起こる。XMLの場合、フィールドに山括弧を含む値を入れようとすると区切り文字(フィールド区切り文字・レコード区切り文字のどちらも)衝突が起こる。テキストファイルではフィールド区切り文字・レコード区切り文字の衝突はよく発生する。

悪意のあるユーザーや攻撃者は、この問題を故意に利用しようとするかもしれない。従って、区切り文字衝突は、セキュリティホールエクスプロイトの原因となり得る。悪意のあるユーザーはSQLHTMLのような言語で、区切り文字衝突を利用してSQLインジェクションクロスサイトスクリプティングのような攻撃を行う。

解決法

区切り文字衝突は非常に一般的な問題なので、それを回避する様々な方法が考案されている。

データストリームに現れそうにない文字(または文字列)を区切り文字として選ぶことによって、問題を回避する方法がある。この方法は多くの場合は通用するが、その文字がデータストリームに現れる確率はゼロではなく、また、悪意のある攻撃に対して安全ではない。よって、この方法は通常はとられない。

ASCII制御文字

ASCIIUnicodeの文字セットではこの問題を回避するために、区切り文字として使用するための非表示の制御文字を用意している。それらの文字はASCIIで28 (0x1C) から31 (0x1F) に割り当てられている。

さらに見る ASCII #, Unicodeでの文字名 ...
ASCII #Unicodeでの文字名一般名使用法
28INFORMATION SEPARATOR FOURファイル分離文字 (FS:file separator)ファイルの終端、または、別のファイルとの間。
29INFORMATION SEPARATOR THREEグループ分離文字 (GS:group separator)データのグループの間。単純な構造のデータファイルでは必要ない。
30INFORMATION SEPARATOR TWOレコード分離文字 (RS:record separator)レコードまたはの終端。
31INFORMATION SEPARATOR ONEユニット分離文字 (US:unit separator)レコードの中のフィールドとフィールドの間。行の中のメンバとメンバの間。
閉じる

ASCII 31のユニット分離文字をフィールド区切り文字として、ASCII 30のレコード分離文字をレコード区切り文字として使用することで、フィールド区切り文字・レコード区切り文字の問題は解決する[17]

エスケープ文字

区切り文字衝突の他の解決法として、エスケープ文字を使用する方法がある。これは、区切り文字の前にエスケープ文字を置くことで、その文字は区切り文字として使用する意図ではないことを明示するものである。言語設計の見地からはこれで十分であるが、以下のような欠点もある。

  • 大量のエスケープ文字が入ることで可読性が低くなる。例えば、Perl正規表現の中で「/」という文字自体を使用したいときは「\/」のように書くが、「//」のように2つ続く場合は「\/\/」のようになる。
  • エスケープ文字として使われる文字を文字通りの文字として表現するたの表記法必要である。例えば、HTMLではエスケープ文字である「&」を文字通りの文字として表現するために「&amp;」という表記法がある。またC言語ではエスケープ文字である「\」を文字通りの文字として表現するために「\\」という表記法がある。
  • 入力するのは簡単だが、その言語をよく知らない人によって理解ができなくなる[18]

エスケープシーケンス

エスケープシーケンスはエスケープ文字と似ているが、衝突する文字そのものの代わりに別の文字列を使用する。

例えば、Perlにおいて文字列リテラルの中にダブルクォートを含ませたいとき、以下のように書く。

print "Nancy said \x22Hello World!\x22 to the crowd.";  ### ダブルクォートの代わりにエスケープシーケンス \x22 を使用

エスケープ文字を使うと以下のようになる。

print "Nancy said \"Hello World!\" to the crowd.";      ### エスケープ文字を使用

エスケープシーケンスの欠点は、それぞれの文字を意味するコードを覚える必要があることである(文字参照を参照)。

2種類の区切り文字

2種類の区切り文字は、区切り文字衝突を避けるためのエスケープ文字やエスケープシーケンスとは別の手段を提供する。いくつかの言語では、シングルクォート (') とダブルクォート (") の2種類を文字列リテラルの区切り文字として使えるようになっている。

Perlでは以下のようになる。

print 'Nancy said "Hello World!" to the crowd.';

このように、エスケープを使わずに表現でき、可読性やコードを覚えなければいけない問題が解決する。しかしこの方法は、文字列が「両方の」種類の文字を含む場合には使えない。

区切り文字の繰り返し

区切り文字衝突を避けるためのエスケープ文字やエスケープシーケンスとは別の手段として、区切り文字の繰り返しがある。これは、衝突する文字を重ねて書く方法である。例えば、区切り文字にダブルクォートを用いるVisual Basicでは、次のようになる。区切り文字の繰り返しは、区切り文字のエスケープと似ている。

print "Nancy said ""Hello World!"" to the crowd."

文字列リテラル内のダブルクォートを2回続けて書くことで、区切り文字でないことを示している。2種類の区切り文字同様、エスケープを使わずに表現できる。しかし、複数のクォートが連続して現れる場合には可読性が低くなる。例えば、上記のソースコード自体を表示させたい場合は、以下のようになる。

print "print ""Nancy said """"Hello World!"""" to the crowd."""

3種類以上の区切り文字

2種類の区切り文字は2種類の範囲指定区切り文字を使用したが、3種類以上の区切り文字はその種類をさらに増やす[19]

以下はPerlでの例である。

print qq^Nancy doesn't want to say "Hello World!" anymore.^;
print qq@Nancy doesn't want to say "Hello World!" anymore.@;
print qq(Nancy doesn't want to say "Hello World!" anymore.);

いずれも、クォート演算子を用いることにより、意図した通りの出力がされる。どんな文字でも区切り文字の働きをさせることができる。この方法がより柔軟であるが、ほとんどの言語は対応していない。PerlとRubyは対応している[20][21]

コンテントバウンダリ

コンテントバウンダリ (content boundary) は、マルチパートのメッセージにおいて、メッセージ中に現れないような文字列をパートの区切り文字として指定する方法である[22]

区切り文字は通常、統計学的に本文中に現れそうにないランダムな文字列から生成する。この後に、特定可能なマーク(UUIDタイムスタンプなど)が続く場合もある。区切り文字が本当に本文中に現れていないか確認することもある。この手法は、区切り文字を短かく、単純なものにすることができ、人間による可読性も向上する。(MIMEヒアドキュメントも参照)

空白・インデント

いくつかのプログラミング言語やコンピュータ用言語では、テキスト中の独立した領域の境界を指定する手段として、空白文字による区切り文字やインデントが使用可能である[23]

正規表現の文法

正規表現を指定する際、Perlで「マッチ(一致)」と「置換」のために構文を単純化するのに代替の区切り文字が用いられる[24]

例えば、Perlでの単純なマッチの操作の構文は以下のようになる。

$string1 = 'Nancy said "Hello World!" to the crowd.';    # 対象の文字列を指定
print $string1 =~ m/[aeiou]+/;                           # 1つ以上の母音にマッチ

この構文は、区切り文字の衝突を避けるために、区切り文字を柔軟に変更できる。

$string1 = 'Nancy said "http://Hello/World.htm" is not a valid address.'; # 対象の文字列を指定
   
print $string1 =~ m@http://@;       # 代替の区切り文字を使用したマッチ
print $string1 =~ m{http://};       # 別の区切り文字を使用。上と同じ結果になる。
print $string1 =~ m!http://!;       # 別の区切り文字を使用。上と同じ結果になる。

ヒアドキュメント

ヒアドキュメントは、特別な終了文字列を指定することによって、任意の内容が含められるようにしている。PHPBashPerlなどの多くの言語が対応している。ヒアドキュメントは、終了文字列の指定から始まり、改行の後、終了文字列が現れるまで続く[25]

以下はPerlによる例である。

print <<ENDOFHEREDOC;
It's very hard to encode a string with "certain characters".

Newlines, commas, and other characters can cause delimiter collisions.
ENDOFHEREDOC

上記のコードを実行すると、以下のように出力される。

It's very hard to encode a string with "certain characters".

Newlines, commas, and other characters can cause delimiter collisions.

内容には、(終了文字列そのもの以外は)どんな文字でも含めることができる。

ASCII-armor

主にバイナリデータのテキスト・エンコーディングのためのメカニズムとして使われるが、ASCII-armorは、いくつかの状況で区切り文字の衝突を避けるためにも使えるプログラミングとシステム管理のテクニックである[26][27]

この手法は複雑なため、小さなアプリケーションと単純なデータ記憶フォーマットにふさわしくない。区切り文字が送られたデータで現れないことを確実とするために、特別なエンコーディング・スキーム(例えばbase64)を使用する。

この手法はマイクロソフトASP.NETなどで使われており、そのシステムの"VIEWSTATE"コンポーネントと密接に関係している[28]

以下の簡略化された例は、この技術が実際にはどのように機能するかについて示す。

次のコード断片は、VIEWSTATEの値がHTMLタグの区切り文字 (") と衝突する例である。このコードは"Well-formed"ではなく、正しく解釈されない。

<input type="hidden" name="__VIEWSTATE" value="BookTitle:Nancy doesn't say "Hello World!" anymore." />

次のコード断片は同じHTMLタグを示しているが、VIEWSTATEの値をbase64でエンコードすることによって、区切り文字と衝突する文字が取り除かれている。

<input type="hidden" name="__VIEWSTATE" value="Qm9va1RpdGxlOk5hbmN5IGRvZXNuJ3Qgc2F5ICJIZWxsbyBXb3JsZCEiIGFueW1vcmUu" />

次のコード断片は、同じHTMLタグをパーセントエンコーディングによって表した例である。

<input type="hidden" name="__VIEWSTATE" value="BookTitle:Nancy%20doesn%27t%20say%20%22Hello%20World!%22%20anymore." />

どんな文字がオリジナルの(デコードされた)テキストに現れるかに関係なく、この手法は区切り文字の衝突を防止し、非互換の文字がHTMLコードに現れないことを確実にする。

配列変換

区切り文字としたい文字列中に存在しない文字を特定してその文字を区切り文字とし、区切り文字とした文字が何であるかを決められた位置(例えば、1文字目とか、最後の位置)に配置する。
例えば、「\10,000」「\300」「aaa;」という文字列がある場合、カンマやセミコロンは区切り文字にならないから、それらの文字列中に存在しない文字、例えば「>」を区切り文字とし、「>\10,000>\300>aaa;>」とする。[29]

関連項目

出典

外部リンク

Wikiwand in your browser!

Seamless Wikipedia browsing. On steroids.

Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.

Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.