Разделитель — это последовательность из одного или нескольких символов для указания границы между отдельными, независимыми областями в обычном тексте , математических выражениях или других потоках данных . [1] [2] Примером разделителя является символ запятой , который действует как разделитель полей в последовательности значений, разделенных запятыми . Другим примером разделителя является временной промежуток, используемый для разделения букв и слов при передаче кода Морзе . [ требуется ссылка ]
В математике разделители часто используются для указания области действия операции и могут встречаться как в виде изолированных символов (например, двоеточие в " "), так и в виде пары противоположно выглядящих символов (например, угловые скобки в ).
Разделители представляют собой один из различных способов указания границ в потоке данных . Декларативная нотация , например, является альтернативным методом (без использования разделителей), который использует поле длины в начале потока данных для указания количества символов, которые содержит поток данных. [3]
Разделители можно охарактеризовать как разделители полей и записей или как разделители-скобки.
Разделители полей разделяют поля данных. Разделители записей разделяют группы полей. [4]
Например, формат CSV использует запятую в качестве разделителя между полями и индикатор конца строки в качестве разделителя между записями :
fname,lname,возраст,зарплатаНэнси,Даволио,33,$30000Эрин,Боракова,28,$25250тони, рафаэль, 35, 28700 долларов
Это определяет простую таблицу базы данных в виде плоского файла, использующего формат файла CSV.
Скобки-разделители, также называемые разделителями блоков, разделителями областей или сбалансированными разделителями, отмечают как начало, так и конец области текста. [5] [6]
Распространенные примеры скобочных разделителей включают в себя: [7]
Исторически вычислительные платформы использовали определенные разделители по соглашению. [15] [16] В следующих таблицах приведено несколько примеров для сравнения.
Языки программирования ( См. также Сравнение языков программирования (синтаксис) ).
Разделители полей и записей ( см. также , ASCII , Управляющий символ ).
Конфликт разделителей — это проблема, которая возникает, когда автор или программист вводит разделители в текст, фактически не намереваясь интерпретировать их как границы между отдельными областями. [4] [18] В случае XML, например, это может произойти всякий раз, когда автор пытается указать символ угловой скобки .
В большинстве типов файлов есть как разделитель полей, так и разделитель записей, оба из которых подвержены коллизиям. Например, в случае файлов со значениями, разделенными запятыми , коллизия полей может возникнуть всякий раз, когда автор пытается включить запятую как часть значения поля (например, salary = "$30,000"), а коллизия разделителей записей может возникнуть всякий раз, когда поле содержит несколько строк. Коллизия как разделителей записей, так и разделителей полей часто встречается в текстовых файлах.
В некоторых контекстах злонамеренный пользователь или злоумышленник может попытаться намеренно использовать эту проблему. Следовательно, коллизия разделителей может быть источником уязвимостей безопасности и эксплойтов . Злонамеренные пользователи могут воспользоваться коллизией разделителей в таких языках, как SQL и HTML, для развертывания таких известных атак, как SQL-инъекция и межсайтовый скриптинг соответственно.
Поскольку коллизия разделителей является очень распространенной проблемой, были изобретены различные методы ее избежания. Некоторые авторы могут попытаться избежать проблемы, выбрав символ-разделитель (или последовательность символов), который, скорее всего, не появится в самом потоке данных. Этот подход ad hoc может быть подходящим, но он обязательно зависит от правильного предположения о том, что появится в потоке данных, и не обеспечивает никакой защиты от злонамеренных коллизий. Поэтому применяются и другие, более формальные соглашения.
Наборы символов ASCII и Unicode были разработаны для решения этой проблемы путем предоставления непечатаемых символов, которые могут использоваться в качестве разделителей. Это диапазон от ASCII 28 до 31.
Использование разделителя единиц ASCII 31 в качестве разделителя полей и разделителя записей ASCII 30 решает проблему разделителей полей и записей, которые появляются в потоке текстовых данных. [19]
Одним из методов избежания коллизий разделителей является использование экранированных символов . С точки зрения дизайна языка они адекватны, но у них есть недостатки:
Escape-последовательности похожи на escape-символы, за исключением того, что они обычно состоят из какой-то мнемоники, а не просто из одного символа. Одно из применений — в строковых литералах , которые включают символ двойной кавычки ("). Например, в Perl код:
print "Нэнси сказала \x22Hello World!\x22 толпе." ; ### use \x22
выдает тот же результат, что и:
напечатайте "Нэнси сказала \"Hello World!\" толпе." ; ### используйте экранированный символ
Одним из недостатков управляющих последовательностей при их использовании людьми является необходимость запоминания кодов, представляющих отдельные символы (см. также: справочник по сущностям символов , справочник по числовым символам ).
В отличие от escape-последовательностей и escape-символов, двойные разделители предоставляют еще один способ избежать коллизии разделителей. Некоторые языки, например, позволяют использовать как одинарную кавычку ('), так и двойную кавычку (") для указания строкового литерала. Например, в Perl :
print 'Нэнси сказала толпе: «Привет, мир!».' ;
производит желаемый вывод без необходимости экранирования. Однако этот подход работает только тогда, когда строка не содержит оба типа кавычек.
В отличие от escape-последовательностей и escape-символов, разделители-заполнители предоставляют еще один способ избежать коллизии разделителей. Visual Basic , например, использует двойные кавычки в качестве разделителей. Это похоже на экранирование разделителя.
распечатать "Нэнси сказала толпе: "Привет, мир!"."
производит желаемый вывод без необходимости экранирования. Однако, как и обычное экранирование, это может стать запутанным, если используется много кавычек. Код для печати исходного кода выше будет выглядеть более запутанным:
print "print ""Нэнси сказала """"Привет, мир!""" толпе."""
В отличие от двойных разделителей, множественные разделители еще более гибки и позволяют избежать коллизий разделителей. [7] : 63
Например, в Perl :
print qq^Нэнси больше не хочет говорить "Hello World!".^ ; print qq@Нэнси больше не хочет говорить "Hello World!".@ ; print qq(Нэнси больше не хочет говорить "Hello World!".) ;
все производят желаемый вывод с помощью использования операторов кавычек, которые позволяют любому удобному символу действовать как разделитель. Хотя этот метод более гибкий, немногие языки его поддерживают. Perl и Ruby — два, которые это делают. [7] : 62 [21]
Граница содержимого — это особый тип разделителя, специально разработанный для противодействия коллизии разделителей. Он работает, позволяя автору указать последовательность символов, которая гарантированно всегда будет указывать границу между частями в многочастном сообщении, без какой-либо другой возможной интерпретации. [22]
Разделитель часто генерируется из случайной последовательности символов, которая статистически маловероятна для появления в содержимом. За ней может следовать идентификационный знак, такой как UUID , временная метка или какой-либо другой отличительный знак. В качестве альтернативы содержимое может быть отсканировано, чтобы гарантировать, что разделитель не появляется в тексте. Это может позволить сделать разделитель короче или проще и повысить удобочитаемость документа человеком. ( См. например , MIME , Here documents ).
Некоторые языки программирования и компьютерные языки допускают использование пробельных разделителей или отступов в качестве средства указания границ между независимыми областями в тексте. [23]
При указании регулярного выражения можно также использовать альтернативные разделители для упрощения синтаксиса операций сопоставления и подстановки в Perl . [24]
Например, простая операция сопоставления может быть указана в Perl с помощью следующего синтаксиса:
$string1 = 'Нэнси сказала толпе "Hello World!".' ; # указать целевую строку print $string1 =~ m/[aeiou]+/ ; # сопоставить одну или несколько гласных
Синтаксис достаточно гибок, чтобы задавать операции сопоставления с альтернативными разделителями, что позволяет легко избежать конфликта разделителей:
$string1 = 'Нэнси сказала, что "http://Hello/World.htm" не является допустимым адресом.' ; # целевая строка print $string1 =~ m@http://@ ; # сопоставление с использованием альтернативного разделителя регулярного выражения print $string1 =~ m{http://} ; # то же, что и предыдущее, но другой разделитель print $string1 =~ m!http://! ; # то же, что и предыдущее, но другой разделитель.
Документ Here позволяет включать произвольное содержимое, описывая специальную конечную последовательность. Многие языки поддерживают это, включая PHP , скрипты bash , ruby и perl . Документ Here начинается с описания того, какой будет конечная последовательность, и продолжается до тех пор, пока эта последовательность не будет видна в начале новой строки. [25]
Вот пример на Perl:
print << ENDOFHEREDOC ; Очень сложно закодировать строку с «определенными символами». Переводы строк, запятые и другие символы могут вызывать конфликты разделителей .
Этот код выведет:
Очень сложно закодировать строку с «определёнными символами».Переводы строк, запятые и другие символы могут вызывать конфликты разделителей.
Используя специальную конечную последовательность, в строке можно использовать любые символы.
Хотя в основном используется как механизм для кодирования текста двоичных данных, ASCII-бронирование является методом программирования и системного администрирования, который также помогает избежать коллизий разделителей в некоторых обстоятельствах. [26] [27] Этот метод отличается от других подходов, описанных выше, поскольку он более сложен и, следовательно, не подходит для небольших приложений и простых форматов хранения данных. Метод использует специальную схему кодирования, такую как base64 , чтобы гарантировать, что разделители или другие значимые символы не появятся в передаваемых данных. Целью является предотвращение многослойного экранирования , например, для двойных кавычек .
Этот метод используется, например, в технологии веб-разработки ASP.NET компании Microsoft и тесно связан с компонентом «VIEWSTATE» этой системы. [28]
Следующий упрощенный пример демонстрирует, как этот метод работает на практике.
Первый фрагмент кода показывает простой HTML-тег , в котором значение VIEWSTATE содержит символы, несовместимые с разделителями самого HTML-тега:
<input type= "hidden" name= "__VIEWSTATE" value= "BookTitle:Нэнси больше не говорит " Hello World!" ." />
Этот первый фрагмент кода некорректно сформирован и поэтому не будет работать должным образом в развернутой системе «в реальном мире».
Для хранения произвольного текста в атрибуте HTML можно использовать HTML-сущности . В этом случае """ заменяет двойные кавычки:
<input type= "hidden" name= "__VIEWSTATE" value= "BookTitle:Нэнси больше не говорит "Hello World!"." />
В качестве альтернативы можно использовать любую кодировку, не включающую символы, имеющие особое значение в контексте, например base64:
<input type= "hidden" name= "__VIEWSTATE" value= "Qm9va1RpdGxlOk5hbmN5IGRvZXNuJ3Qgc2F5ICJIZWxsbyBXb3JsZCEiIGFueW1vcmUu" />
Или процентное кодирование :
<input type= "hidden" name= "__VIEWSTATE" value= "BookTitle:Нэнси%20не%27т%20сказать%20%22Привет%20Мир!%22%20больше." />
Это предотвращает столкновение разделителей и гарантирует, что несовместимые символы не появятся внутри HTML-кода, независимо от того, какие символы появляются в исходном (декодированном) тексте. [28]
{{citation}}
: CS1 maint: числовые имена: список авторов ( ссылка )