stringtranslate.com

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

В компьютерном программировании интерполяция строк (или интерполяция переменных , подстановка переменных или расширение переменных ) — это процесс оценки строкового литерала , содержащего один или несколько заполнителей , дающий результат, в котором заполнители заменяются соответствующими им значениями. Это форма простой обработки шаблонов [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]

  1. Заменить и расширить заполнители : создание новой строки из исходной с помощью операций поиска–замены. Найти ссылку на переменную (заполнитель), заменить ее значением ее переменной. Этот алгоритм не предлагает стратегии кэширования.
  2. Разделить и объединить строку : разделение строки на массив, слияние ее с соответствующим массивом значений, затем объединение элементов путем конкатенации. Разделенная строка может быть кэширована для повторного использования.

Проблемы безопасности

Интерполяция строк, как и конкатенация строк, может привести к проблемам безопасности. Если данные пользовательского ввода неправильно экранированы или отфильтрованы, система будет подвержена атакам 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

Синтаксис скрипта языка разметки ColdFusion (CFML):

яблоки  =  4 ; writeOutput ( "У меня есть #яблоки# яблок" );

Синтаксис тега:

<cfset  apples  =  4 > <cfoutput> У меня есть # яблок # яблок </cfoutput>

Результат будет следующим:

У меня есть 4 яблока.

CoffeeScript

яблоки = 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

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

<?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 (тискрипт)

В 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 .NET

Начиная с Visual Basic 14, в Visual Basic поддерживается интерполяция строк. [17]

имя = "Том" Консоль . WriteLine ( $ "Привет, {имя}" )  

Результат будет следующим:

Привет, Том.

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

Примечания

  1. ^ «Обеспечение строгого разделения модели и представления в шаблонизаторах», Т. Парр (2004), конференция WWW2004.
  2. ^ "Интерполяция в Perl". Это гораздо аккуратнее, чем повторное использование оператора конкатенации '.'.
  3. ^ "smallest-template-system/Simplest algorithms", онлайн-руководство по системам шаблонов-заполнителей.
  4. ^ "Безопасная интерполяция строк". google-caja.googlecode.com . Архивировано из оригинала 2012-10-19.
  5. ^ "Строки - Руководство по программированию на C#". 15 марта 2024 г.
  6. ^ "предложение: Go 2: интерполяция строк #34174". GitHub .
  7. ^ "предложение: Go 2: интерполяция строк, вычисляющая строку и список выражений #50554". GitHub .
  8. ^ "Язык программирования Apache Groovy - Синтаксис". groovy-lang.org . Получено 20.06.2021 .
  9. ^ "Haxe - Руководство - Интерполяция строк". Haxe - Кроссплатформенный инструментарий . Получено 12.09.2017 .
  10. ^ https://docs.oracle.com/en/java/javase/23/migrate/significant-changes-jdk-release.html
  11. ^ "Шаблонные литералы (Шаблонные строки) - JavaScript | MDN". 31 мая 2024 г.
  12. ^ «Учебник Python: 7.1.1. Форматированные строковые литералы».
  13. ^ «Справочник по языку Python: 2.4.3. Форматированные строковые литералы».
  14. ^ «PEP 498 — Интерполяция литеральных строк».
  15. ^ «Анонс Rust 1.58.0: захваченные идентификаторы в строках формата». 2022-01-13.
  16. ^ «Строки и символы — язык программирования Swift (Swift 5.5)». docs.swift.org . Получено 20 июня 2021 г. .
  17. ^ КэтлинДоллард. "Интерполированные строки - Visual Basic". docs.microsoft.com . Получено 20 июня 2021 г. .