stringtranslate.com

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

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

Синтаксис

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

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

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

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

""

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

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

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

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

"[^"]*"

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

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

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

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

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

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

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

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

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

{{Навигационное окно |name=Нули |title=[[wikt:Null|Нуллы]] в [[вычислениях]] }}

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

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

 - title : Пример многострочной строки в теле YAML : | Это многострочная строка. Здесь могут появляться "специальные" метасимволы . Длина этой строки отображается отступом.        

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

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

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

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

$y = "x" ; $y = x ;    

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

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

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

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

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

Недостатки:

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

Конструктор функций

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

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

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

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

При использовании кавычек, если кто-то хочет представить сам разделитель в строковом литерале, он сталкивается с проблемой коллизии разделителей . Например, если разделитель — двойная кавычка, он не может просто представить саму двойную кавычку литералом """, поскольку вторая кавычка интерпретируется как конец строкового литерала, а не как значение строки, и аналогично он не может написать, "This is "in quotes", but invalid."поскольку средняя часть в кавычках вместо этого интерпретируется как вне кавычек. Существуют различные решения, наиболее общим из которых является использование управляющих последовательностей, таких как "\""или "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 символов, за исключением пробельных символов, скобок или обратной косой черты, которые образуют end-of-string-id (его цель — повторяться для обозначения конца строки, сокращенно eos id ), затем требуется открывающая скобка (для обозначения конца eos id). Затем следует фактическое содержимое литерала: Могут использоваться любые символы последовательности (за исключением того, что она не может содержать закрывающую скобку, за которой следует eos id, за которым следует кавычка), и, наконец, — для завершения строки — требуется закрывающая скобка, eos id и кавычка. Простейший случай
такого литерала — с пустым содержимым и пустым eos id: R"()".
Сам eos id может содержать кавычки: R""(I asked, "Can you hear me?")""является допустимым литералом (eos id "здесь.)
Escape-последовательности не работают в необработанных строковых литералах.

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

q" end-of-string-id newline content newline end-of-string-id "

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

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

Многократное цитирование

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

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

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

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

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формата «character», хотя при наличии других обходных путей она, как правило, не используется:

char buffer [ 32 ]; snprintf ( buffer , sizeof buffer , "Это %cin кавычек.%c" , 34 , 34 );      

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

Последовательности выхода из положения

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

Один символ выбирается в качестве префикса, чтобы задать кодировки для символов, которые трудно или невозможно включить напрямую. Чаще всего это обратная косая черта ; в дополнение к другим символам, ключевым моментом является то, что сама обратная косая черта может быть закодирована как двойная обратная косая черта \\, а для разделенных строк сам разделитель может быть закодирован с помощью экранирования, например, с помощью \"for ". Регулярное выражение для таких экранированных строк может быть задано следующим образом, как указано в спецификации ANSI C : [1] [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\" 

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

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

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

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

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

эхо 'foo bar' 

и

echo  -e "foo\nbar" 

оба являются допустимыми bash, выдавая:

фубар

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

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

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

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

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

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

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

Мотивация

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Проблемы

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

l  =  [ 'foo' ,  'bar'  'zork' ]

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

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

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

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

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

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

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

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

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

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

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

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

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

'' "" `` // м// qr// s/// y // / q{} qq{} qx{} qw{} м {} qr{} s{}{} tr {}{} y {}{}               

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

'20' х "0010 0000" б "00100000" б

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

Интерполяция строк

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

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

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

выдает результат:

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

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

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

printf "%s сказал %s толпе людей." , $name , $greeting ;   

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

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

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

которые производят вывод вроде:

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

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

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

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

Например:

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

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

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

Примечания

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

Ссылки

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

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