В компьютерном программировании интерполяция строк (или интерполяция переменных , подстановка переменных или расширение переменных ) — это процесс оценки строкового литерала , содержащего один или несколько заполнителей , дающий результат, в котором заполнители заменяются соответствующими им значениями. Это форма простой обработки шаблонов [1] или, в формальных терминах, форма квазицитирования (или интерпретации логической подстановки ). Заполнитель может быть именем переменной или, в некоторых языках, произвольным выражением, в любом случае оцениваемым в текущем контексте .
Интерполяция строк является альтернативой построению строки посредством конкатенации , которая требует повторного заключения и раскавычивания; [2] или подстановки в строку формата printf , где переменная находится далеко от места ее использования. Сравните:
яблоки = 4 puts "У меня есть #{ яблок } яблок." # интерполяция строк puts "У меня есть " + String ( яблоки ) + " яблоки." # конкатенация строк puts "У меня есть %d яблок." % яблоки # формат строки
Обычно предлагаются два типа литеральных выражений: один с включенной интерполяцией, другой без. Неинтерполированные строки также могут экранировать последовательности , в этом случае они называются необработанной строкой , хотя в других случаях это отдельно, что дает три класса необработанной строки, неинтерполированной (но экранированной) строки, интерполированной (и экранированной) строки. Например, в оболочках Unix строки в одинарных кавычках являются необработанными, в то время как строки в двойных кавычках интерполируются. Заполнители обычно представлены голым или именованным символом (обычно $
или %
), например, $apples
или %apples
, или с фигурными скобками, например {apples}
, иногда и тем, и другим, например ${apples}
. В некоторых случаях могут использоваться дополнительные спецификаторы форматирования (как в printf), например {apples:3}
, а в некоторых случаях сами спецификаторы форматирования могут быть интерполированы, например {apples:width}
, . Расширение строки обычно происходит во время выполнения .
Поддержка интерполяции строк в разных языках сильно различается. Некоторые языки не поддерживают интерполяцию строк, а вместо этого используют конкатенацию, простые функции форматирования или библиотеки шаблонов. Интерполяция строк распространена во многих языках программирования , которые интенсивно используют строковые представления данных, таких как Apache Groovy , Julia , Kotlin , Perl , PHP , Python , Ruby , Scala , Swift , Tcl и большинство оболочек Unix .
Существует два основных типа алгоритмов расширения переменных для интерполяции переменных : [3]
Интерполяция строк, как и конкатенация строк, может привести к проблемам безопасности. Если данные пользовательского ввода неправильно экранированы или отфильтрованы, система будет подвержена атакам SQL-инъекции , скриптовой инъекции , XML-внешней сущности (XXE) и межсайтового скриптинга (XSS). [4]
Пример SQL-инъекции:
запрос = " "SELECT x, y, z FROM Table WHERE id='$id'
Если $id
заменить на " "';
, выполнение этого запроса уничтожит все данные в DELETE FROM Table; SELECT * FROM Table WHERE id='
Table
.
ДАННЫЕ ( яблоки ) = 4 . ЗАПИСЬ | У меня есть { яблоки } яблок |.
Результат будет следующим:
У меня есть 4 яблока.
яблоки = 4 echo "У меня есть $apples яблок" # или echo "У меня есть ${ apples } яблок"
Результат будет следующим:
У меня есть 4 яблока.
яблоки = 4 print ( "У меня есть $(apples) яблок" ) # или print ( "У меня есть {0} яблок" % яблоки )
Результат будет следующим:
У меня есть 4 яблока.
вар яблоки = 4 ; вар бананы = 3 ; Console.WriteLine ( $ " У меня есть {яблоки} яблок" ); Console.WriteLine ( $ " У меня есть {яблоки + бананы} фруктов" );
[5]
Результат будет следующим:
У меня 4 яблока У меня 7 фруктов
Синтаксис скрипта языка разметки ColdFusion (CFML):
яблоки = 4 ; writeOutput ( "У меня есть #яблоки# яблок" );
Синтаксис тега:
<cfset apples = 4 > <cfoutput> У меня есть # яблок # яблок </cfoutput>
Результат будет следующим:
У меня есть 4 яблока.
яблоки = 4 console . log "У меня есть #{ яблоки } яблок"
Результат будет следующим:
У меня есть 4 яблока.
int яблоки = 4 , бананы = 3 ; print ( 'У меня есть $ яблок яблок.' ); print ( 'У меня есть ${ яблоки + бананы } фруктов.' );
Результат будет следующим:
У меня 4 яблока. У меня 7 фруктов.
По состоянию на 2022 год [обновлять]в Go нет интерполяции строк. Было несколько предложений по интерполяции строк в следующей версии языка, Go 2. [6] [7] Вместо этого Go использует строки формата printf в fmt.Sprintf
функции, конкатенацию строк или библиотеки шаблонов, такие как text/template
.
В Groovy интерполированные строки называются GStrings: [8]
def quality = "superhero" final age = 52 def sentence = "Разработчик является $quality, если он ${age <= 42 ? 'young' : 'seasoned'}" println sentence
Результат будет следующим:
Разработчик — супергерой, если он опытный.
var apples = 4 ; var bananas = 3 ; trace ( 'У меня есть $ apples яблок.' ); trace ( 'У меня есть ${ apples + bananas } фруктов.' );
Вывод будет следующим: [9]
У меня 4 яблока. У меня 7 фруктов.
В Java 21 и Java 22 в качестве предварительной версии была реализована интерполяция строк. Можно было напрямую использовать константу STR из java.lang.StringTemplate.
enum Stage { тест , qa , prod } запись Развертывание ( изображение UUID , этап ) {} var Deploy = new Deploy ( UUID.randomUUID ( ) , Stage.test ) STR . "Установка \{deploy.image()} на Stage \{deploy.stage()} ..."var deploy = new Deploy ( UUID . randomUUID (), Stage . prod ) STR . "Установка \{deploy.image()} на Stage \{deploy.stage()} ..."
Они были удалены в Java 23 из-за проблем с дизайном. [10]
JavaScript , как и стандарт ECMAScript 2015 (ES6), поддерживает интерполяцию строк с использованием обратных кавычек ``
. Эта функция называется литералами шаблона . [11] Вот пример:
const яблоки = 4 ; const бананы = 3 ; console.log ( `У меня есть $ { apples } яблок` ) ; console.log ( ` У меня есть $ { apples + bananas } фруктов` );
Результат будет следующим:
У меня 4 яблока У меня 7 фруктов
Шаблонные литералы также можно использовать для многострочных строк:
console . log ( `Это первая строка текста. Это вторая строка текста.` );
Результат будет следующим:
Это первая строка текста. Это вторая строка текста.
яблоки = 4 банана = 3 print ( "У меня есть $apples яблок и $bananas бананов, всего получается $ ( яблок + бананов ) штук фруктов." )
Результат будет следующим:
У меня 4 яблока и 3 банана, всего получается 7 фруктов.
val quality = "супергерой" val apples = 4 val bananas = 3 val sentence = "Разработчик - это $ quality . У меня есть ${ apples + bananas } fruit" println ( sentence )
Результат будет следующим:
Разработчик - супергерой. У меня 7 фруктов.
def яблоки = 4 ; def бананы = 3 ; Console . WriteLine ( $ "У меня есть $apples яблок." ); Console . WriteLine ( $ "У меня есть $(яблоки + бананы) фруктов." );
Он также поддерживает расширенные функции форматирования, такие как:
def fruit = [ "apple" , "banana" ]; Console . WriteLine ( $ < #У меня есть ..$(fruit; "\n"; f => f + "s")#>);
Результат будет следующим:
яблоки бананы
Nim обеспечивает интерполяцию строк через модуль strutils. Форматированные строковые литералы, вдохновленные Python F-string, предоставляются через модуль strformat, макрос strformat проверяет, что строка формата правильно сформирована и типизирована, а затем расширяется в исходный код Nim во время компиляции.
import strutils , strformat var apples = 4 var bananas = 3 echo "У меня есть яблоки стоимостью $1 " . format ( apples ) echo fmt"У меня есть {apples} яблок" echo fmt"У меня есть {apples + bananas} фруктов" # Многострочное эхо fmt" "" У меня есть { яблок } яблок" "" # Отладка форматирования echo fmt"У меня есть {apples=} яблок" # Пользовательские символы openChar и closeChar echo fmt ( "У меня есть (яблоки) {яблоки}" , '(' , ')' ) # Обратная косая черта внутри форматированного строкового литерала echo fmt" "" { " yep \ nope" } "" "
Результат будет следующим:
У меня 4 яблока У меня 4 яблока У меня 7 фруктов У меня 4 яблока У меня есть яблоки=4 яблока У меня 4 {яблока} да, опа
пусть numberOfApples = "4" ; в "У меня есть ${ numberOfApples } яблок"
Результат будет следующим:
У меня есть 4 яблока.
const Яблоки := 4 const Бананы := 3 Println ( "У меня есть `(Яблоки) яблоки.\n" ) Println ( "У меня есть `(Яблоки+Бананы) фрукты.\n" )
Результат будет следующим:
У меня 4 яблока. У меня 7 фруктов.
my $apples = 4 ; my $bananas = 3 ; print "У меня есть $apples яблок.\n" ; print "У меня есть @{[$apples+$bananas]} фруктов.\n" ; # Использует интерполяцию массива Perl (@).
Результат будет следующим:
У меня 4 яблока. У меня 7 фруктов.
<?php $apples = 5 ; $bananas = 3 ; echo "Есть $apples яблок и $bananas бананов. \n " ; echo "У меня есть { $apples } яблок и { $bananas } бананов." ;
Результат будет следующим:
Есть 5 яблок и 3 банана. У меня есть 5 яблок и 3 банана.
Python поддерживает интерполяцию строк, начиная с версии 3.6, называемую «форматированными строковыми литералами». [12] [13] [14] Такой литерал начинается с f
или F
перед открывающей кавычкой и использует фигурные скобки для заполнителей:
яблоки = 4 бананы = 3 print ( f 'У меня есть { яблоки } яблоки и { бананы } бананы' )
Результат будет следующим:
У меня 4 яблока и 3 банана.
яблоки = 4 puts "У меня есть #{ яблок } яблок" # Формат строковых приложений для сравнения: puts "У меня есть %s яблок" % apples puts "У меня есть %{a} яблок" % { a : яблоки }
Результат будет следующим:
У меня есть 4 яблока.
Rust не имеет общей интерполяции строк, но предоставляет схожую функциональность с помощью макросов, называемых «Захваченные идентификаторы в строках формата», представленных в версии 1.58.0, выпущенной 13 января 2022 г. [15]
Rust обеспечивает форматирование через модуль std::fmt, который взаимодействует с различными макросами, такими как format!, write! и print!. Эти макросы преобразуются в исходный код Rust во время компиляции, при этом каждый аргумент взаимодействует с форматировщиком. Форматировщик поддерживает позиционные параметры, именованные параметры, типы аргументов, определение различных признаков форматирования и захват идентификаторов из среды.
let ( apples , bananas ) = ( 4 , 3 ); // println! захватывает идентификаторы при форматировании: сама строка не интерполируется Rust. println! ( "There are {apples} apples and {bananas} bananas." );
Результат будет следующим:
Есть 4 яблока и 3 банана.
Scala 2.10+ предоставляет общее средство для произвольной обработки строкового литерала и поддерживает интерполяцию строк с использованием включенных s
и f
строковых интерполяторов. Также возможно писать собственные или переопределять стандартные.
Интерполятор f
— это макрос компилятора, который переписывает строку формата со встроенными выражениями как вызов String.format. Он проверяет, что строка формата правильно сформирована и типизирована.
Интерполяция строк Scala 2.10+ позволяет встраивать ссылки на переменные непосредственно в обработанные строковые литералы. Вот пример:
val apples = 4 val bananas = 3 //до Scala 2.10 printf ( "У меня есть %d яблок\n" , яблоки ) println ( "У меня есть %d яблок" format apples ) //Scala 2.10+ println ( s"У меня есть $ apples apples" ) println ( s"У меня есть ${ apples + bananas } fruits" ) println ( f"У меня есть $ apples %d apples" )
Результат будет следующим:
У меня есть 4 яблока.
В Sciter любая функция с именем, начинающимся с $, считается интерполирующей функцией, поэтому интерполяция настраивается и зависит от контекста:
вар яблок = 4 вар бананов = 3 вар domElement = ...; domElement . $ content ( <p> У меня есть { яблоки } яблоки < /p> ) ; domElement . $append ( <p> У меня есть { яблоки + бананы } фрукты < /p>);
Где
domElement . $content ( <p> У меня есть { яблоки } яблоки </p> ) ;
компилируется в это:
domElement . html = "<p>У меня есть " + яблоки . toHtmlString () + " яблоки</p>" ;
яблоки = 4 ; бананы = 3 Вывод = "У меня есть " яблок " яблок." Вывод = "У меня есть " ( яблоки + бананы ) " фруктов."
Результат будет следующим:
У меня 4 яблока. У меня 7 фруктов.
В Swift новое строковое значение может быть создано из смеси констант, переменных, литералов и выражений путем включения их значений в строковый литерал. [16] Каждый элемент, вставленный в строковый литерал, заключен в пару скобок с префиксом в виде обратной косой черты.
пусть яблоки = 4 напечатайте ( "У меня есть \ (яблоки) яблоки" )
Результат будет следующим:
У меня есть 4 яблока.
Язык команд инструментов всегда поддерживал интерполяцию строк во всех строках, заключенных в кавычки.
set apples 4 puts "У меня есть $apples яблоки."
Результат будет следующим:
У меня 4 яблока.
Для того чтобы фактически отформатировать, а не просто заменить значения, существует функция форматирования.
набор яблок 4 помещает [ формат "У меня есть %d яблок." $apples ]
Начиная с версии 1.4, TypeScript поддерживает интерполяцию строк с использованием обратных кавычек ``
. Вот пример:
var apples : number = 4 ; console . log ( `У меня есть ${ apples } яблок` );
Результат будет следующим:
У меня есть 4 яблока.
Функцию console.log
можно использовать как printf
функцию. Пример выше можно переписать следующим образом:
var apples : number = 4 ; console . log ( "У меня есть %d яблок" , apples );
Выход остается прежним.
Начиная с Visual Basic 14, в Visual Basic поддерживается интерполяция строк. [17]
имя = "Том" Консоль . WriteLine ( $ "Привет, {имя}" )
Результат будет следующим:
Привет, Том.
Это гораздо аккуратнее, чем повторное использование оператора конкатенации '.'.