stringtranslate.com

Строковый литерал

Строковый литерал или анонимная строка [1] — это литерал строкового значения в исходном коде компьютерной программы . В современных языках программирования обычно используется последовательность символов в кавычках, формально «разделители в скобках», например x = "foo", где "foo"— строковый литерал со значением foo. Такие методы, как escape-последовательности, можно использовать, чтобы избежать проблемы столкновения разделителей (проблемы с скобками) и позволить встраивать разделители в строку. Существует множество альтернативных обозначений для указания строковых литералов, особенно в сложных случаях. Точное обозначение зависит от рассматриваемого языка программирования . Тем не менее, существуют общие рекомендации, которым следуют большинство современных языков программирования.

Синтаксис

Разделители в квадратных скобках

Большинство современных языков программирования используют разделители скобок (также сбалансированные разделители ) для указания строковых литералов. Двойные кавычки являются наиболее распространенными разделителями кавычек:

"Всем привет!"

Пустая строка буквально записывается парой кавычек без каких-либо символов между ними:

""

Некоторые языки либо разрешают, либо требуют использования одинарных кавычек вместо двойных (строка должна начинаться и заканчиваться кавычками одного и того же типа, а тип кавычек может давать или не давать немного разную семантику):

'Всем привет!'

Эти кавычки непарные (один и тот же символ используется в качестве открывающего и закрывающего), что является пережитком технологии пишущих машинок , которая была предшественником самых ранних компьютерных устройств ввода и вывода.

В терминах регулярных выражений базовый строковый литерал в кавычках задается как:

"[^"]*"

Это означает, что строковый литерал записывается как: кавычка, за которой следует ноль, один или несколько символов, не являющихся кавычками, а затем кавычка . На практике это часто усложняется экранированием, другими разделителями и исключением символов новой строки.

Парные разделители

В ряде языков предусмотрены парные разделители, в которых открывающий и закрывающий разделители различны. Они также часто допускают вложенные строки, поэтому разделители могут быть встроены, если они парные, но все равно приводят к коллизии разделителей при внедрении непарного закрывающего разделителя. Примеры включают PostScript , в котором используются круглые скобки, как в (The quick (brown fox))и m4 , в котором в качестве начального разделителя используется обратный апостроф (`), а в качестве конечного разделителя – апостроф ('). Tcl допускает как кавычки (для интерполированных строк), так и фигурные скобки (для необработанных строк), как в "The quick brown fox"or {The quick {brown fox}}; это происходит из-за одинарных кавычек в оболочках Unix и использования фигурных скобок в C для составных операторов, поскольку блоки кода в Tcl синтаксически то же самое, что и строковые литералы - чтобы сделать это возможным, важно, чтобы разделители были парными.

Набор символов Юникода включает парные (отдельные открывающие и закрывающие) версии как одинарных, так и двойных кавычек :

"Всем привет!" 'Всем привет!' "Всем привет!" "Всем привет!"

Однако они используются редко, поскольку многие языки программирования их не регистрируют (единственным исключением являются парные двойные кавычки, которые можно использовать в Visual Basic .NET ). Непарные знаки предпочтительнее из соображений совместимости, поскольку их легче печатать на широком спектре клавиатур, и поэтому даже на языках, где они разрешены, многие проекты запрещают их использование в исходном коде.

Разделители пробелов

Строковые литералы могут заканчиваться символами новой строки.

Одним из примеров являются параметры шаблона MediaWiki .

{{Навбокс |имя=Нулевые значения |title=[[wikt:Null|Nulls]] в [[computing]] }}

Для многострочных строк может быть специальный синтаксис.

В YAML строковые литералы могут указываться относительным расположением пробелов и отступов.

 - title : пример многострочной строки в теле YAML : | Это многострочная строка. Здесь могут появиться «специальные» метасимволы . Размер этой строки представлен отступом.        

Без разделителей

Некоторые языки программирования, такие как Perl и PHP, в некоторых контекстах допускают строковые литералы без каких-либо разделителей. Например, в следующей программе Perl red, greenи blueявляются строковыми литералами, но не заключаются в кавычки:

%map = ( красный => 0x00f , синий => 0x0f0 , зеленый => 0xf00 );          

В большинстве контекстов Perl рассматривает незарезервированные последовательности буквенно-цифровых символов как строковые литералы. Например, следующие две строки Perl эквивалентны:

= "х" ; = х ;    

Декларативная нотация

В исходном языке программирования FORTRAN (например) строковые литералы записывались в так называемой нотации Холлерита , где за десятичным числом символов следовала буква H, а затем символы строки:

35 HA Пример строкового литерала Холлерита    

Этот декларативный стиль записи контрастирует с кавычками -разделителями в квадратных скобках, поскольку он не требует использования сбалансированных символов в квадратных скобках по обе стороны строки.

Преимущества:

Недостатки:

Однако это не является недостатком, когда префикс генерируется алгоритмом, что наиболее вероятно. [ нужна цитата ]

Функции конструктора

В C++ есть два стиля строк: один унаследован от C (с разделителем "), а более безопасный — std::stringв стандартной библиотеке C++. Этот std::stringкласс часто используется так же, как строковый литерал в других языках, и его часто предпочитают строкам в стиле C из-за его большей гибкости и безопасности. Но он имеет снижение производительности для строковых литералов, поскольку std::stringобычно память распределяется динамически, и ему приходится копировать в него строковый литерал в стиле C во время выполнения.

До C++11 не было литерала для строк C++ (C++11 допускает "this is a C++ string"sиспользование sв конце литерала), поэтому использовался обычный синтаксис конструктора, например:

все они имеют одну и ту же интерпретацию. Начиная с C++11, появился новый синтаксис конструктора:

Столкновение разделителей

Если при использовании кавычек кто-то хочет представить сам разделитель в строковом литерале, он сталкивается с проблемой коллизии разделителей . Например, если разделителем является двойная кавычка, нельзя просто представить саму двойную кавычку с помощью литерала, """поскольку вторая кавычка интерпретируется как конец строкового литерала, а не как значение строки, и аналогичным образом нельзя записать "This is "in quotes", but invalid."как вместо этого средняя кавычка интерпретируется как вне кавычек. Существуют различные решения, наиболее универсальным из которых является использование escape-последовательностей, таких как "\""или "This is \"in quotes\" and properly escaped.", но есть и много других решений.

Парные кавычки, такие как фигурные скобки в Tcl, допускают вложенные строки, такие как, {foo {bar} zork}но не решают проблему столкновения разделителей, поскольку несбалансированный закрывающий разделитель не может быть просто включен, как в {}}.

Удвоение

В ряде языков, включая Pascal , BASIC , DCL , Smalltalk , SQL , J и Fortran , конфликты разделителей избегаются за счет удвоения кавычек, которые должны быть частью самого строкового литерала:

 'Эта строка Паскаля '' содержит два апострофа '' '
 «Я сказал: «Ты меня слышишь?»»»

Двойное цитирование

Некоторые языки, такие как Fortran , Modula-2 , JavaScript , Python и PHP , допускают использование более одного разделителя кавычек; в случае двух возможных разделителей это называется двойными кавычками . Обычно это означает, что программисту разрешено использовать как одинарные, так и двойные кавычки взаимозаменяемо — каждый литерал должен использовать то или другое.

 «Это яблоко Джона».  «Я спросил: «Ты меня слышишь?»

Однако это не позволяет иметь один литерал с обоими разделителями. Эту проблему можно обойти, используя несколько литералов и конкатенацию строк :

 «Я сказал: «Это»  +  «Джона»  +  «яблоко».

В Python есть конкатенация строковых литералов , поэтому последовательные строковые литералы объединяются даже без оператора, поэтому это можно сократить до:

 «Я сказал: «Это яблоко Джона ».

Цитирование разделителя

В C++11 появились так называемые необработанные строковые литералы . Они состоят, по существу, из

R" end-of-string-id ( контент ) end-of-string-id " ,

то есть после того, как R"программист может ввести до 16 символов, за исключением пробелов, круглых скобок и обратной косой черты, которые образуют идентификатор конца строки (его цель состоит в том, чтобы повториться для обозначения конца строки, для краткости eos id) . ), то требуется открывающая скобка (для обозначения конца идентификатора eos). Затем следует фактическое содержимое литерала: можно использовать любые символы последовательности (за исключением того, что они не могут содержать закрывающую скобку, за которой следует идентификатор eos после кавычки), и, наконец, для завершения строки — закрывающую скобку, идентификатор eos. , и требуется цитата.
Самый простой случай такого литерала — с пустым содержимым и пустым идентификатором eos: R"()".
Идентификатор eos сам может содержать кавычки: R""(I asked, "Can you hear me?")""это допустимый литерал (идентификатор eos находится "здесь).
Escape-последовательности не работают в необработанных строковых литералах.

D поддерживает несколько разделителей в кавычках, причем такие строки начинаются с q"плюса открывающего разделителя и заканчиваются соответствующим закрывающим разделителем и ". Доступные пары разделителей: (), <>, {}и []; непарный разделитель, не являющийся идентификатором, является собственным закрывающим разделителем. Парные разделители вложены друг в друга, поэтому это q"(A pair "()" of parens in quotes)"допустимый литерал; пример с невложенным /символом: q"/I asked, "Can you hear me?"/".
Подобно C++11, D позволяет использовать литералы в стиле «здесь-документ» с идентификаторами конца строки:

q" end-of-string- id содержимое новой строки "

В D идентификатор конца строки должен быть идентификатором (буквенно-цифровыми символами).

В некоторых языках программирования, таких как sh и Perl , существуют разные разделители, которые обрабатываются по-разному, например, выполняется ли интерполяция строк или нет, и поэтому необходимо соблюдать осторожность при выборе того, какой разделитель использовать; см. различные типы строк ниже.

Множественное цитирование

Дальнейшим расширением является использование множественных кавычек , которое позволяет автору выбирать, какие символы должны указывать границы строкового литерала.

Например, в Perl :

qq^Я сказал: «Ты меня слышишь?»^ qq@Я сказал: «Ты меня слышишь?»@ qq§Я сказал: «Ты меня слышишь?»§

все дают желаемый результат. Хотя эта нотация более гибкая, ее поддерживают немногие языки; Помимо Perl, их также поддерживают Ruby (под влиянием Perl) и C++11 . Вариантом множественных кавычек является использование строк в стиле документа .

Lua (начиная с версии 5.1) предоставляет ограниченную форму множественного цитирования, в частности, для возможности вложения длинных комментариев или встроенных строк. Обычно для разделения литеральных строк используются [[и ]](начальная новая строка удалена, в противном случае - необработанная), но открывающие скобки могут включать в себя любое количество знаков равенства, и только закрывающие скобки с одинаковым количеством знаков закрывают строку. Например:

local  ls  =  [=[ Эту запись можно использовать для путей Windows: local path = [[C:\Windows\Fonts]] ] =]

Множественные кавычки особенно полезны для регулярных выражений , которые содержат обычные разделители, такие как кавычки, поскольку это позволяет избежать необходимости их экранирования. Ранним примером является sed , где в команде замены разделители косой черты по умолчанию могут быть заменены другим символом, как в .s/regex/replacement//s,regex,replacement,

Функции конструктора

Другой вариант, который редко используется в современных языках, — использовать функцию для создания строки, а не представлять ее через литерал. Обычно это не используется в современных языках, поскольку вычисления выполняются во время выполнения, а не во время анализа.

Например, ранние версии BASIC не включали escape-последовательности или какие-либо другие обходные пути, перечисленные здесь, и поэтому вместо этого требовалось использовать функцию CHR$, которая возвращает строку, содержащую символ, соответствующий ее аргументу. В ASCII кавычка имеет значение 34, поэтому для представления строки с кавычками в системе ASCII следует написать

«Я сказал:» + CHR$ ( 34 ) + «Вы меня слышите?» + CHR$ ( 34 )      

В C аналогичная возможность доступна через sprintfспецификатор %cформата «символ», хотя при наличии других обходных путей это обычно не используется:

буфер символов [ 32 ]; snprintf ( buffer , sizeof buffer , «Это %cin quotes.%c» , 34 , 34 );      

Эти функции-конструкторы также можно использовать для представления непечатаемых символов, хотя вместо них обычно используются escape-последовательности. Похожий метод можно использовать в C++ с std::stringоператором строкообразования.

Escape-последовательности

Escape-последовательности — это общий метод представления символов, которые иначе трудно представить напрямую, включая разделители, непечатаемые символы (например, символы возврата), символы новой строки и пробелы (которые иначе невозможно различить визуально), и имеют долгую историю. Соответственно, они широко используются в строковых литералах, а добавление escape-последовательности (к одному символу или по всей строке) называется экранированием .

Один символ выбирается в качестве префикса, чтобы дать кодировку для символов, которые трудно или невозможно включить напрямую. Чаще всего это обратная косая черта ; Помимо других символов, ключевым моментом является то, что сама обратная косая черта может быть закодирована как двойная обратная косая черта \\, а для строк с разделителями сам разделитель может быть закодирован путем экранирования, скажем, \"for ". Регулярное выражение для таких экранированных строк может быть задано следующим образом , как указано в спецификации ANSI C : [2] [a]

"(\\.|[^\\"])*"

означает «кавычку; за которой следует ноль или более экранированных символов (обратная косая черта, за которой следует что-то, возможно, обратная косая черта или кавычка), или неэкранирующийся символ, не являющийся кавычкой; заканчивающийся кавычкой» – единственная проблема заключается в различении завершающая цитата из цитаты, которой предшествует обратная косая черта, которую можно экранировать. За обратной косой чертой могут следовать несколько символов, например \uFFFF, в зависимости от схемы экранирования.

Затем экранированную строку необходимо лексически проанализировать , преобразуя экранированную строку в неэкранированную строку, которую она представляет. Это делается на этапе оценки общего лексирования компьютерного языка: оценщик лексера общего языка выполняет свой собственный лексер для экранированных строковых литералов.

Помимо прочего, должна быть возможность закодировать символ, который обычно завершает строковую константу, плюс должен быть какой-то способ указать сам escape-символ. Escape-последовательности не всегда красивы и просты в использовании, поэтому многие компиляторы предлагают и другие способы решения распространенных проблем. Однако escape-последовательности решают любую проблему с разделителями, и большинство компиляторов интерпретируют escape-последовательности. Когда escape-символ находится внутри строкового литерала, это означает «это начало escape-последовательности». Каждая escape-последовательность определяет один символ, который должен быть помещен непосредственно в строку. Фактическое количество символов, требуемых в escape-последовательности, варьируется. Escape-символ находится в верхней/левой части клавиатуры, но редактор его переведет, поэтому его невозможно записать в строку напрямую. Обратная косая черта используется для представления escape-символа в строковом литерале.

Многие языки поддерживают использование метасимволов внутри строковых литералов. Метасимволы интерпретируются по-разному в зависимости от контекста и языка, но обычно представляют собой своего рода «команду обработки» для представления печатаемых или непечатаемых символов.

Например, в строковом литерале C , если за обратной косой чертой следует такая буква, как «b», «n» или «t», то это представляет собой непечатаемый символ возврата , новой строки или символа табуляции соответственно. Или, если за обратной косой чертой следуют 1–3 восьмеричные цифры, то эта последовательность интерпретируется как представление произвольной кодовой единицы с указанным значением в кодировке литерала (например, соответствующий код ASCII для литерала ASCII). Позже это было расширено, чтобы обеспечить более современную запись шестнадцатеричного кода символов:

«Я сказал: \t\t\x22 Ты меня слышишь? \x22\n »

Примечание. Не все последовательности в списке поддерживаются всеми анализаторами, и могут существовать другие escape-последовательности, которых нет в списке.

Вложенное экранирование

Когда код на одном языке программирования встроен в другой, для встроенных строк может потребоваться несколько уровней экранирования. Это особенно часто встречается в регулярных выражениях и SQL-запросах на других языках или в других языках внутри сценариев оболочки. Такое двойное экранирование часто сложно читать и писать.

Неправильное заключение вложенных строк в кавычки может представлять собой уязвимость безопасности. При использовании ненадежных данных, например в полях данных SQL-запроса, следует использовать подготовленные операторы, чтобы предотвратить атаку путем внедрения кода . В версиях PHP со 2 по 5.3 существовала функция, называемая магическими кавычками , которая автоматически экранировала строки (для удобства и безопасности), но из-за проблем была удалена, начиная с версии 5.4.

Необработанные строки

Некоторые языки предоставляют метод указания того, что литерал должен обрабатываться без какой-либо интерпретации, специфичной для языка. Это позволяет избежать необходимости экранирования и дает более разборчивые строки.

Необработанные строки особенно полезны, когда необходимо экранировать общий символ, особенно в регулярных выражениях (вложенных в строковые литералы), где \широко используется обратная косая черта, а также в путях DOS/Windows , где обратная косая черта используется в качестве разделителя пути. Обилие обратных косых черт известно как синдром наклоненной зубочистки , и его можно уменьшить, используя необработанные строки. Сравните экранированные и необработанные пути в C#:

 "Путь Windows: C:\\Foo\\Bar\\Baz\\" @"Путь Windows: C:\Foo\Bar\Baz\" 

Крайние примеры возникают, когда они объединены: пути по унифицированному соглашению об именах начинаются с \\, и, таким образом, экранированное регулярное выражение, соответствующее UNC-имени, начинается с 8 обратных косых черт, "\\\\\\\\", из-за необходимости экранирования строки и регулярного выражения. Использование необработанных строк уменьшает это число до 4 (экранирование в регулярном выражении), как в C# @"\\\\".

В документах XML разделы CDATA позволяют использовать такие символы, как & и <, без того, чтобы синтаксический анализатор XML пытался интерпретировать их как часть структуры самого документа. Это может быть полезно при включении обычного текста и кода сценариев, чтобы сохранить правильность формата документа .

<![CDATA[ if (path!=null && deep<2) { add(path); } ]]>

Многострочные строковые литералы

Во многих языках строковые литералы могут содержать буквальные символы новой строки, занимающие несколько строк. Альтернативно, символы новой строки можно экранировать, чаще всего как \n. Например:

эхо 'фу бар' 

и

echo  -e "foo\nbar" 

оба действительны bash, производя:

фубар

Языки, допускающие буквальный перевод строки, включают bash, Lua, Perl, PHP, R и Tcl. В некоторых других языках строковые литералы не могут включать символы новой строки.

Две проблемы с многострочными строковыми литералами — это начало и конец новой строки, а также отступы. Если начальный или конечный разделители находятся на отдельных строках, появляются дополнительные символы новой строки, а если нет, то разделитель затрудняет чтение строки, особенно для первой строки, отступ которой часто отличается от остальных. Кроме того, литерал не должен иметь отступов, поскольку сохраняются начальные пробелы — это нарушает поток кода, если литерал встречается в коде с отступом.

Наиболее распространенным решением этих проблем являются строковые литералы в стиле документа . Формально говоря, здесь документ — это не строковый литерал, а потоковый или файловый литерал. Они возникают в сценариях оболочки и позволяют использовать литерал в качестве входных данных для внешней команды. Открывающий разделитель — это <<ENDместо, где ENDможет быть любое слово, а закрывающий разделитель находится ENDна отдельной строке и служит границей содержимого — это <<связано с перенаправлением стандартного ввода из литерала. Поскольку разделитель является произвольным, это также позволяет избежать проблемы столкновения разделителей. Они также позволяют удалять начальные табуляции с помощью вариантного синтаксиса, <<-ENDхотя ведущие пробелы не удаляются. Тот же синтаксис с тех пор был принят для многострочных строковых литералов во многих языках, особенно в Perl, и здесь они также называются документами и сохраняют синтаксис, несмотря на то, что они являются строками и не требуют перенаправления. Как и в случае с другими строковыми литералами, для них иногда может быть указано другое поведение, например интерполяция переменных.

Python, чьи обычные строковые литералы не допускают буквальных символов новой строки, вместо этого имеет специальную форму строк, предназначенную для многострочных литералов, называемую тройными кавычками . Они используют тройной разделитель '''или """. Эти литералы особенно используются для встроенной документации, известной как строки документации .

Tcl допускает буквальные символы новой строки в строках и не имеет специального синтаксиса для работы с многострочными строками, хотя разделители могут размещаться в строках сами по себе, а начальные и конечные символы новой строки удаляются с помощью string trim, а также string mapмогут использоваться для удаления отступов.

Конкатенация строковых букв

Некоторые языки обеспечивают конкатенацию строковых литералов , при которой соседние строковые литералы неявно объединяются в один литерал во время компиляции. Это особенность C, [8] [9] C++, [10] D, [11] Ruby, [12] и Python, [13] которые скопировали ее из C. [14] Примечательно, что эта конкатенация происходит при компиляции. во время лексического анализа (как этап после первоначальной токенизации) и контрастирует как с конкатенацией строк во время выполнения (обычно с помощью +оператора) [15], так и с конкатенацией во время свертывания констант , которая происходит во время компиляции, но на более позднем этапе ( после анализа фразы или «парсинга»). Большинство языков, таких как C#, Java [16] и Perl, не поддерживают неявную конкатенацию строковых литералов и вместо этого требуют явной конкатенации, например, с помощью оператора +(это также возможно в D и Python, но незаконно в C/C++ – см. ниже); в этом случае конкатенация может происходить во время компиляции посредством свертывания констант или может быть отложена до времени выполнения.

Мотивация

В языке C, откуда возникли это понятие и термин, конкатенация строковых литералов была введена по двум причинам: [17]

На практике это позволяет осуществлять конкатенацию строк на ранних этапах компиляции («перевод», в частности, как часть лексического анализа), без необходимости анализа фраз или постоянного свертывания. Например, следующие допустимы для C/C++:

char * s = "привет," "мир" ; printf ( "привет," "мир" );     

Однако следующее недействительно:

char * s = "привет," + "мир" ; printf ( "привет," + "мир" );       

Это связано с тем, что строковые литералы имеют тип массива (C) или (C++), который нельзя добавить; в большинстве других языков это не ограничение.char [n]const char [n]

Это особенно важно при использовании в сочетании с препроцессором C , чтобы обеспечить возможность вычисления строк после предварительной обработки, особенно в макросах. [14] Простой пример:

char * file_and_message = __FILE__ ": сообщение" ;    

будет (если файл называется ac) расширится до:

char * file_and_message = "ac" ": сообщение" ;    

который затем объединяется, что эквивалентно:

char * file_and_message = "ac: сообщение" ;   

Распространенным вариантом использования является создание строк формата printf или scanf , где спецификаторы формата задаются макросами. [19] [20]

В более сложном примере используется преобразование целых чисел в строку (препроцессором) для определения макроса, который расширяется до последовательности строковых литералов, которые затем объединяются в один строковый литерал с именем файла и номером строки: [21]

#define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) #define AT __FILE__ ":" TOSTRING(__LINE__)

Помимо синтаксических требований C/C++, неявная конкатенация представляет собой форму синтаксического сахара , упрощающую разделение строковых литералов на несколько строк, избегая необходимости продолжения строки (посредством обратной косой черты) и позволяя добавлять комментарии к частям строк. Например, в Python регулярное выражение можно прокомментировать следующим образом: [22]

ре . компилировать ( "[A-Za-z_]"  # буква или подчеркивание  "[A-Za-z0-9_]*"  # буква, цифра или подчеркивание  )

Проблемы

Неявная конкатенация строк не требуется современными компиляторами, которые реализуют свертывание констант и вызывают трудно распознаваемые ошибки из-за непреднамеренной конкатенации из-за пропуска запятой, особенно в вертикальных списках строк, например:

l  =  [ 'foo' ,  'бар'  'зорк' ]

Соответственно, он не используется в большинстве языков, и было предложено исключить его из D [23] и Python. [14] Однако удаление этой функции нарушает обратную совместимость, а замена ее оператором конкатенации приводит к проблемам приоритета: конкатенация строковых литералов происходит во время лексического анализа, до вычисления оператора, но конкатенация с помощью явного оператора происходит одновременно с другими операторами. , следовательно, приоритет является проблемой, потенциально требующей скобок для обеспечения желаемого порядка вычислений.

Более тонкая проблема заключается в том, что в C и C++ [24] существуют разные типы строковых литералов, и их объединение имеет поведение, определяемое реализацией, что представляет потенциальную угрозу безопасности. [25]

Различные виды струн

Некоторые языки предоставляют более одного вида литералов, которые имеют разное поведение. Это особенно используется для обозначения необработанных строк (без экранирования) или для отключения или включения интерполяции переменных, но имеет и другие применения, например, для различения наборов символов. Чаще всего это делается путем изменения символа цитирования или добавления префикса или суффикса. Это сравнимо с префиксами и суффиксами целочисленных литералов , например, для обозначения шестнадцатеричных чисел или длинных целых чисел.

Один из самых старых примеров — сценарии оболочки, где одинарные кавычки обозначают необработанную строку или «литеральную строку», а двойные кавычки содержат escape-последовательности и интерполяцию переменных.

Например, в Python необработанным строкам предшествует знак rили R– сравнить 'C:\\Windows'с r'C:\Windows'(хотя необработанная строка Python не может заканчиваться нечетным количеством обратных косых черт). Python 2 также различает два типа строк: 8-битные строки ASCII («байты») (по умолчанию), явно обозначаемые префиксом bили B, и строки Unicode, обозначаемые префиксом uили U. [26] в то время как в Python 3 строки по умолчанию имеют формат Unicode, а байты представляют собой отдельный bytesтип, который при инициализации с кавычками должен иметь префикс b.

Нотация C# для необработанных строк называется @-кавычками.

@"C:\Foo\Bar\Baz\"

Хотя это отключает экранирование, оно позволяет удвоить кавычки, что позволяет представлять кавычки внутри строки:

@"Я сказал: "Привет."""

C++11 допускает необработанные строки, строки Юникода (UTF-8, UTF-16 и UTF-32) и строки широких символов, определяемые префиксами. Он также добавляет литералы для существующего C++ string, который обычно предпочтительнее существующих строк в стиле C.

В Tcl строки, разделенные скобками, являются буквальными, а строки, разделенные кавычками, имеют экранирование и интерполяцию.

В Perl имеется большое разнообразие строк, которые более формально считаются операторами и известны как кавычки и операторы, подобные кавычкам . К ним относятся как обычный синтаксис (фиксированные разделители), так и общий синтаксис, позволяющий выбирать разделители; к ним относятся: [27]

'' "" `` // m// qr// s/// y // / q{} qq{} qx{} qw{} m{} qr{} s{}{} tr {}{} да {}{}               

REXX использует символы-суффиксы для указания символов или строк, используя их шестнадцатеричный или двоичный код. Например,

'20' x "0010 0000" b "00100000" b

все они дают пробел , избегая вызова функции X2C(20).

Строковая интерполяция

В некоторых языках строковые литералы могут содержать заполнители, ссылающиеся на переменные или выражения в текущем контексте , которые оцениваются (обычно во время выполнения). Это называется интерполяцией переменных или, в более общем смысле, интерполяцией строк . Языки, поддерживающие интерполяцию, обычно различают строковые литералы, которые интерполируются, от неинтерполируемых. Например, в sh-совместимых оболочках Unix (а также в Perl и Ruby) строки в двойных кавычках (разделенных кавычками ") интерполируются, а строки в одинарных кавычках (разделенных апострофом ") - нет. строковые литералы иногда называют «необработанными строками», но это отличается от «необработанной строки» в смысле экранирования. Например, в Python строка с префиксом rили Rбез экранирования или интерполяции, обычная строка (без префикса). ) имеет экранирование, но не имеет интерполяции, а строка с префиксом fили Fимеет экранирование и интерполяцию.

Например, следующий код Perl :

$name = "Нэнси" ; $greeting = "Привет, мир" ; print "$name сказал $приветствие толпе людей." ;     

производит вывод:

Нэнси сказала «Привет, мир» толпе людей.

В этом случае метасимвол ($) (не путать с символом в операторе присваивания переменной) интерпретируется как указание на интерполяцию переменной и требует некоторого экранирования, если его нужно вывести буквально.

Это следует противопоставить printfфункции, которая выдает тот же результат, используя такие обозначения, как:

printf "%s сказал %s толпе людей." , $имя , $приветствие ;   

но не выполняет интерполяцию: это %sзаполнитель в строке формата printf , но сами переменные находятся вне строки.

Это контрастирует с «необработанными» строками:

print '$name сказал $приветствие толпе людей.' ; 

которые производят вывод, например:

$name сказал $приветствие толпе людей.

Здесь символы $ не являются метасимволами и не интерпретируются как имеющие какое-либо значение, кроме обычного текста.

Встраивание исходного кода в строковые литералы

Языки, которым не хватает гибкости в указании строковых литералов, делают особенно громоздким написание программного кода, генерирующего другой программный код. Это особенно верно, когда язык генерации такой же или похож на язык вывода.

Например:

Тем не менее, некоторые языки особенно хорошо адаптированы для создания такого рода самоподобного вывода, особенно те, которые поддерживают несколько вариантов предотвращения столкновения разделителей.

Использование строковых литералов в качестве кода, генерирующего другой код, может иметь неблагоприятные последствия для безопасности, особенно если выходные данные хотя бы частично основаны на ненадежном пользовательском вводе. Это особенно актуально в случае веб-приложений, где злонамеренные пользователи могут воспользоваться такими слабостями, чтобы подорвать работу приложения, например, путем проведения атаки с помощью SQL-инъекции .

Смотрите также

Примечания

  1. ^ Приведенное здесь регулярное выражение само по себе не заключено в кавычки и не экранировано, чтобы избежать путаницы.
  2. ^ ab Поскольку эта escape-последовательность представляет конкретную кодовую единицу, а не определенный символ, то, какую кодовую точку (если таковая имеется) она представляет, зависит от кодировки строкового литерала, в котором она находится.

Рекомендации

  1. ^ «Введение в Java — MFC 158 G» . Строковые литералы (или константы) называются «анонимными строками».
  2. ^ «Грамматика ANSI C (Lex)» . Лю.се. _ Проверено 22 июня 2016 г.
  3. ^ ab «Приложение B. Символы, строки и правила экранирования». Realworldhaskell.org . Проверено 22 июня 2016 г.
  4. ^ ab "Строка". сайт mozilla.org . Проверено 22 июня 2016 г.
  5. ^ abcdefghijklm «Escape-последовательности (C)». microsoft.com . Проверено 22 июня 2016 г.
  6. ^ ab «Обоснование международного стандарта — языки программирования — C» (PDF) . 5.10. Апрель 2003 г., стр. 52, 153–154, 159. Архивировано (PDF) из оригинала 6 июня 2016 г. Проверено 17 октября 2010 г.
  7. ^ «6.35 Символ <ESC> в константах», Руководство GCC 4.8.2 , получено 8 марта 2014 г.
  8. ^ Проект стандарта C11 , Проект комитета WG14 N1570 — 12 апреля 2011 г., 5.1.1.2 Этапы перевода, стр. 11: «6. Токены соседних строковых литералов объединяются».
  9. ^ Синтаксис C: конкатенация строковых литералов
  10. ^ Проект стандарта C++11 , «Рабочий проект стандарта для языка программирования C++» (PDF) ., 2.2 Фазы трансляции [lex.phases], с. 17: «6. Токены соседних строковых литералов объединяются». и 2.14.5 Строковые литералы [lex.string], примечание 13, с. 28–29: «На этапе трансляции 6 (2.2) соседние строковые литералы объединяются».
  11. ^ D Язык программирования, Лексический анализ, «Строковые литералы»: «Соседние строки объединяются с помощью оператора ~ или путем простого сопоставления:»
  12. ^ рубин: Язык программирования Ruby, Язык программирования Ruby, 19 октября 2017 г. , получено 19 октября 2017 г.
  13. ^ Справочник по языку Python, 2. Лексический анализ, 2.4.2. Конкатенация строковых литералов: «Допускаются несколько соседних строковых литералов (разделенных пробелами), возможно, с использованием разных соглашений о кавычках, и их значение такое же, как и их конкатенация».
  14. ^ abc Python-ideas, «Неявная конкатенация строковых литералов считается вредной?», Гвидо ван Россум, 10 мая 2013 г.
  15. ^ Справочник по языку Python, 2. Лексический анализ, 2.4.2. Конкатенация строковых литералов: «Обратите внимание, что эта функция определена на синтаксическом уровне, но реализована во время компиляции. Оператор «+» должен использоваться для объединения строковых выражений во время выполнения».
  16. ^ «Строки (Учебные пособия по Java™> Изучение языка Java> Числа и строки)» . Docs.oracle.com . 28 февраля 2012 г. Проверено 22 июня 2016 г.
  17. ^ Обоснование языка программирования ANSI C. Силиконовый пресс. 1990. с. 31. ISBN 0-929306-07-4., 3.1.4 Строковые литералы: «Длинную строку можно продолжить на несколько строк, используя продолжение строки с обратной косой чертой и новой строкой, но эта практика требует, чтобы продолжение строки начиналось с первой позиции следующей строки. Для обеспечения большей гибкости компоновки и для решения некоторых проблем предварительной обработки (см. §3.8.3) Комитет ввел конкатенацию строковых литералов. Два строковых литерала подряд склеиваются вместе (без нулевого символа в середине), образуя один объединенный строковый литерал. Это дополнение Язык C позволяет программисту расширять строковый литерал за пределы конца физической строки без необходимости использования механизма обратной косой черты и новой строки и тем самым разрушения схемы отступов программы. Явный оператор конкатенации не был введен, поскольку конкатенация является лексическая конструкция, а не операция времени выполнения».
  18. ^ Обоснование языка программирования ANSI C. Силиконовый пресс. 1990. с. 6566. ИСБН 0-929306-07-4., 3.8.3.2 Оператор #: «Оператор # был введен для создания строк. Его можно использовать только в расширении #define. Он приводит к замене следующего имени формального параметра строковым литералом, образованным путем преобразования в строку фактического токена аргумента. В сочетании с конкатенацией строковых литералов (см. §3.1.4) использование этого оператора позволяет создавать строки так же эффективно, как и путем замены идентификатора внутри строки. Пример в Стандарте иллюстрирует эту возможность».
  19. ^ Журнал пользователей C/C++, том 19, стр. 50
  20. ^ «Python — зачем разрешать конкатенацию строковых литералов?». Переполнение стека . Проверено 22 июня 2016 г.
  21. ^ «LINE__ в строку (stringify) с использованием директив препроцессора» . Decompile.com . 12 октября 2006 г. Проверено 22 июня 2016 г.
  22. ^ Справочник по языку Python, 2. Лексический анализ, 2.4.2. Конкатенация строковых литералов: «Эту функцию можно использовать для уменьшения количества необходимых обратных косых черт, для удобного разделения длинных строк на длинные строки или даже для добавления комментариев к частям строк, например:
  23. ^ Система отслеживания проблем DLang - Проблема 3827 - Предупредить и затем запретить неявное объединение соседних строковых литералов.
  24. ^ Проект стандарта C++11 , «Рабочий проект стандарта для языка программирования C++» (PDF) ., 2.14.5 Строковые литералы [lex.string], примечание 13, с. 28–29: «Любые другие объединения условно поддерживаются поведением, определяемым реализацией».
  25. ^ «STR10-C. Не объединяйте строковые литералы разных типов - Безопасное кодирование - Стандарты безопасного кодирования CERT» . Архивировано из оригинала 14 июля 2014 года . Проверено 3 июля 2014 г.
  26. ^ «2. Лексический анализ — документация Python 2.7.12rc1» . python.org . Проверено 22 июня 2016 г.
  27. ^ "perlop - perldoc.perl.org" . perl.org . Проверено 22 июня 2016 г.

Внешние ссылки