Literal de string - String literal

Um literal de string ou string anônimo é um tipo de literal em programação para a representação de um valor de string dentro do código-fonte de um programa de computador . Na maioria das vezes em linguagens modernas, esta é uma sequência de caracteres entre aspas (formalmente " delimitadores entre colchetes "), como em x = "foo", onde "foo"é uma string literal com valor foo- as aspas não fazem parte do valor, e deve-se usar um método como sequências de escape para evitar o problema de colisão do delimitador e permitir que os próprios delimitadores sejam incorporados em uma string. No entanto, existem várias notações alternativas para especificar literais de string, casos particularmente mais complicados, e a notação exata depende da linguagem de programação individual em questão. No entanto, existem algumas diretrizes gerais que a maioria das linguagens de programação modernas segue.

Sintaxe

Delimitadores entre colchetes

A maioria das linguagens de programação modernas usa delimitadores de colchetes (também delimitadores balanceados ) para especificar literais de string. Aspas duplas são os delimitadores de aspas mais comuns usados:

 "Hi There!"

Uma string vazia é literalmente escrita por um par de aspas sem nenhum caractere entre:

 ""

Alguns idiomas permitem ou exigem o uso de aspas simples em vez de aspas duplas (a string deve começar e terminar com o mesmo tipo de aspa e o tipo de aspa pode ou não fornecer semânticas ligeiramente diferentes):

 'Hi There!'

Essas aspas não estão emparelhadas (o mesmo caractere é usado como abridor e mais próximo), o que é um resquício da tecnologia da máquina de escrever que foi a precursora dos primeiros dispositivos de entrada e saída de computador.

Em termos de expressões regulares , um literal básico de string entre aspas é fornecido como:

"[^"]*"

Isso significa que um literal de string é escrito como: uma aspa, seguida por zero, um ou mais caracteres sem aspas, seguida por uma aspa . Na prática, isso geralmente é complicado pelo escape de outros delimitadores e pela exclusão de novas linhas.

Delimitadores emparelhados

Vários idiomas fornecem delimitadores emparelhados, em que os delimitadores de abertura e fechamento são diferentes. Eles também costumam permitir strings aninhadas, portanto, delimitadores podem ser incorporados, desde que estejam emparelhados, mas ainda resultam em colisão de delimitadores para incorporar um delimitador de fechamento desemparelhado. Os exemplos incluem PostScript , que usa parênteses, como em (The quick (brown fox))e m4 , que usa crase (`) como delimitador inicial e o apóstrofo (') como delimitador final. Tcl permite aspas (para strings interpoladas) e colchetes (para strings brutas), como em "The quick brown fox"ou {The quick {brown fox}}; isso deriva das aspas simples em shells Unix e do uso de colchetes em C para instruções compostas, uma vez que blocos de código são em Tcl sintaticamente a mesma coisa que literais de string - que os delimitadores estão emparelhados é essencial para tornar isso viável.

Embora o conjunto de caracteres Unicode inclua versões emparelhadas (abertura e fechamento separados) de aspas simples e duplas, usadas no texto, principalmente em outras línguas além do inglês, raramente são usadas em linguagens de programação (porque o ASCII é preferido e não estão incluídas em ASCII):

 “Hi There!”
 ‘Hi There!’
 „Hi There!“
 «Hi There!»

As aspas duplas emparelhadas podem ser usadas no Visual Basic .NET , mas muitas outras linguagens de programação não as aceitarão. Marcas desemparelhadas são preferidas para compatibilidade, já que são mais fáceis de digitar em uma ampla variedade de teclados e, portanto, mesmo em linguagens onde são permitidas, muitos projetos proíbem seu uso como código-fonte.

Delimitadores de espaço em branco

Literais de string podem ser encerrados por novas linhas.

Um exemplo são os parâmetros de modelo do MediaWiki .

 {{Navbox
 |name=Nulls
 |title=[[wikt:Null|Nulls]] in [[computing]]
 }}

Pode haver sintaxe especial para strings de várias linhas.

Em YAML , os literais de string podem ser especificados pelo posicionamento relativo de espaços em branco e indentação.

    - title: An example multi-line string in YAML
      body : |
        This is a multi-line string.
        "special" metacharacters may
        appear here. The extent of this string is
        represented by indentation.

Sem delimitadores

Algumas linguagens de programação, como Perl e PHP, permitem literais de string sem quaisquer delimitadores em alguns contextos. No programa seguinte Perl, por exemplo, red, greene bluesão strings literais, mas são sem aspas:

%map = (red => 0x00f, blue => 0x0f0, green => 0xf00);

O Perl trata as sequências não reservadas de caracteres alfanuméricos como literais de string na maioria dos contextos. Por exemplo, as duas linhas a seguir de Perl são equivalentes:

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

Notação declarativa

Na linguagem de programação FORTRAN original (por exemplo), os literais de string eram escritos na chamada notação Hollerith , onde uma contagem decimal do número de caracteres era seguida pela letra H e, em seguida, pelos caracteres da string:

35HAn example Hollerith string literal

Este estilo de notação declarativa é contrastado com aspas delimitadoras entre colchetes , porque ele não requer o uso de caracteres "entre colchetes" balanceados em ambos os lados da string.

Vantagens:

  • elimina a pesquisa de texto (para o caractere delimitador) e, portanto, requer significativamente menos sobrecarga
  • evita o problema de colisão do delimitador
  • permite a inclusão de metacaracteres que podem ser confundidos com comandos
  • pode ser usado para compressão de dados bastante eficaz de strings de texto simples

Desvantagens:

  • este tipo de notação está sujeito a erros se usado como entrada manual por programadores
  • é necessário cuidado especial no caso de codificações multibyte

No entanto, isso não é uma desvantagem quando o prefixo é gerado por um algoritmo, como é o caso mais provável.

Funções de construtor

C ++ tem dois estilos de string, um herdado de C (delimitado por ") e o mais seguro std::stringna Biblioteca Padrão C ++. A std::stringclasse é freqüentemente usada da mesma maneira que um literal de string seria usado em outras linguagens, e geralmente é preferida a strings de estilo C por sua maior flexibilidade e segurança. Mas ele vem com uma penalidade de desempenho para literais de string, já que std::stringnormalmente aloca memória dinamicamente e deve copiar o literal de string de estilo C para ele em tempo de execução.

Antes do C ++ 11, não havia literal para strings C ++ (C ++ 11 permite "this is a C++ string"scom o sno final do literal), então a sintaxe normal do construtor foi usada, por exemplo:

  • std::string str = "initializer syntax";
  • std::string str("converting constructor syntax");
  • std::string str = string("explicit constructor syntax");

todos os quais têm a mesma interpretação. Desde C ++ 11, também há uma nova sintaxe de construtor:

  • std::string str{"uniform initializer syntax"};
  • auto str = "constexpr literal syntax"s;

Delimitador de colisão

Ao usar aspas, se alguém deseja representar o próprio delimitador em um literal de string, enfrenta o problema da colisão do delimitador . Por exemplo, se o delimitador for uma aspa dupla, não se pode simplesmente representar uma aspa dupla pelo literal, """já que a segunda aspa é interpretada como o final do literal de string, não como o valor da string e, da mesma forma, não se pode escrever "This is "in quotes", but invalid."como a parte citada do meio é interpretada como fora das aspas. Existem várias soluções, sendo que a finalidade mais geral é usar sequências de escape, como "\""ou "This is \"in quotes\" and properly escaped.", mas existem muitas outras soluções.

As aspas emparelhadas, como colchetes em Tcl, permitem strings aninhadas, como, {foo {bar} zork}mas não resolvem de outra forma, o problema de colisão de delimitadores, uma vez que um delimitador de fechamento não balanceado não pode ser simplesmente incluído, como em {}}.

Dobrando

Diversas linguagens, incluindo Pascal , BASIC , DCL , Smalltalk , SQL , J e Fortran , evitam a colisão do delimitador dobrando as aspas que devem ser parte do próprio literal de string:

  'This Pascal string''contains two apostrophes'''
  "I said, ""Can you hear me?"""

Citação dupla

Algumas linguagens, como Fortran , Modula-2 , JavaScript , Python e PHP permitem mais de um delimitador de aspas; no caso de dois delimitadores possíveis, isso é conhecido como citação dupla . Normalmente, isso consiste em permitir que o programador use aspas simples ou duplas de forma intercambiável - cada literal deve usar uma ou a outra.

  "This is John's apple."
  'I said, "Can you hear me?"'

Isso não permite ter um único literal com ambos os delimitadores, no entanto. Isso pode ser contornado usando vários literais e usando concatenação de string :

  'I said, "This is ' + "John's" + ' apple."'

Python tem concatenação de literal de string , portanto, literais de string consecutivas são concatenados mesmo sem um operador, então isso pode ser reduzido a:

  'I said, "This is '"John's"' apple."'

D suporta alguns delimitadores de aspas, com essas strings começando com q"[e terminando com ]"ou de forma semelhante para outro caractere delimitador (qualquer um de () <> {} ou []). D também suporta aqui strings de estilo de documento por meio de sintaxe semelhante.

Em algumas linguagens de programação, como sh e Perl , existem diferentes delimitadores que são tratados de forma diferente, como fazer interpolação de strings ou não, e, portanto, deve-se tomar cuidado ao escolher qual delimitador usar; veja diferentes tipos de strings , abaixo.

Citação múltipla

Uma extensão adicional é o uso de citações múltiplas , que permite ao autor escolher quais caracteres devem especificar os limites de um literal de string.

Por exemplo, em Perl :

qq^I said, "Can you hear me?"^
qq@I said, "Can you hear me?"@
qq§I said, "Can you hear me?"§

todos produzem o resultado desejado. Embora essa notação seja mais flexível, poucos idiomas a suportam; além de Perl, Ruby (influenciado por Perl) e C ++ 11 também os suportam. No C ++ 11, as strings brutas podem ter vários delimitadores, começando com R"delimiter(e terminando com )delimiter". O delimitador pode ter de zero a 16 caracteres e pode conter qualquer membro do conjunto de caracteres de origem básica, exceto caracteres de espaço em branco, parênteses ou barra invertida. Uma variante das citações múltiplas é o uso de strings no estilo de documento aqui .

Lua (a partir de 5.1) fornece uma forma limitada de citações múltiplas, particularmente para permitir o aninhamento de comentários longos ou strings embutidas. Normalmente se usa [[e ]]para delimitar strings literais (nova linha inicial retirada, caso contrário, brutos), mas os colchetes de abertura podem incluir qualquer número de sinais de igual, e apenas colchetes de fechamento com o mesmo número de sinais fecham a string. Por exemplo:

local ls = [=[
This notation can be used for Windows paths: 
local path = [[C:\Windows\Fonts]]
]=]

As citações múltiplas são particularmente úteis com expressões regulares que contêm delimitadores usuais, como aspas, pois isso evita a necessidade de escapá-los. Um exemplo inicial é o sed , onde no comando de substituição os delimitadores de barra padrão podem ser substituídos por outro caractere, como em . s/regex/replacement//s,regex,replacement,

Funções de construtor

Outra opção, raramente usada em linguagens modernas, é usar uma função para construir uma string, em vez de representá-la por meio de um literal. Isso geralmente não é usado em linguagens modernas porque a computação é feita em tempo de execução, e não em tempo de análise.

Por exemplo, as primeiras formas de BASIC não incluíam sequências de escape ou quaisquer outras soluções alternativas listadas aqui e, portanto, era necessário usar a CHR$função, que retorna uma string contendo o caractere correspondente ao seu argumento. Em ASCII, as aspas têm o valor 34, portanto, para representar uma string com aspas em um sistema ASCII, escrever-se-ia

"I said, " + CHR$(34) + "Can you hear me?" + CHR$(34)

Em C, um recurso semelhante está disponível por meio sprintfdo %cespecificador de formato de "caractere", embora na presença de outras soluções alternativas isso geralmente não seja usado:

sprintf("This is %cin quotes.%c", 34, 34);

Essas funções construtoras também podem ser usadas para representar caracteres não imprimíveis, embora sequências de escape sejam geralmente usadas em seu lugar. Uma técnica semelhante pode ser usada em C ++ com o std::stringoperador de stringificação.

Sequências de escape

Sequências de escape são uma técnica geral para representar caracteres que, de outra forma, seriam difíceis de representar diretamente, incluindo delimitadores, caracteres não imprimíveis (como backspaces), novas linhas e caracteres de espaço em branco (que de outra forma seriam impossíveis de distinguir visualmente) e têm uma longa história. Eles são amplamente usados ​​em strings literais, e adicionar uma sequência de escape (para um único caractere ou em toda a string) é conhecido como escape .

Um caractere é escolhido como prefixo para fornecer codificações para caracteres que são difíceis ou impossíveis de incluir diretamente. Mais comumente, é a barra invertida ; além de outros caracteres, um ponto-chave é que a própria barra invertida pode ser codificada como uma barra invertida dupla \\e, para strings delimitadas, o próprio delimitador pode ser codificado escapando, digamos, por \"". Uma expressão regular para essas strings escapadas pode ser fornecida da seguinte maneira , conforme encontrado na especificação ANSI C :

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

significando "uma aspa; seguido por zero ou mais de um caractere de escape (barra invertida seguida por algo, possivelmente barra invertida ou aspas) ou um caractere sem escape e sem aspas; terminando em aspas" - o único problema é distinguir o encerrar a citação a partir de uma citação precedida por uma barra invertida, que pode ser evitada. Vários caracteres podem seguir a barra invertida, como \uFFFF, dependendo do esquema de escape.

Uma string com escape deve então ser analisada lexicamente , convertendo a string com escape na string sem escape que ela representa. Isso é feito durante a fase de avaliação da lexing geral da linguagem de computador: o avaliador do lexer da linguagem geral executa seu próprio lexer para literais de string de escape.

Entre outras coisas, deve ser possível codificar o caractere que normalmente termina a constante da string, além disso, deve haver alguma maneira de especificar o próprio caractere de escape. As sequências de escape nem sempre são bonitas ou fáceis de usar, portanto, muitos compiladores também oferecem outros meios de resolver os problemas comuns. As sequências de escape, no entanto, resolvem todos os problemas de delimitador e a maioria dos compiladores interpreta as sequências de escape. Quando um caractere de escape está dentro de um literal de string, significa "este é o início da sequência de escape". Cada seqüência de escape especifica um caractere que deve ser colocado diretamente na string. O número real de caracteres necessários em uma sequência de escape varia. O caractere de escape está na parte superior / esquerda do teclado, mas o editor o traduzirá, portanto, não pode ser gravado diretamente em uma string. A barra invertida é usada para representar o caractere de escape em um literal de string.

Muitas linguagens suportam o uso de metacaracteres dentro de literais de string. Metacaracteres têm interpretações variadas dependendo do contexto e da linguagem, mas geralmente são um tipo de 'comando de processamento' para representar caracteres impressos ou não imprimíveis.

Por exemplo, em um literal de string C , se a barra invertida for seguida por uma letra como "b", "n" ou "t", isso representará um backspace não imprimível , uma nova linha ou um caractere de tabulação , respectivamente. Ou, se a barra invertida for seguida por 1-3 dígitos octais , essa sequência será interpretada como representando o caractere arbitrário com o código ASCII especificado . Posteriormente, isso foi estendido para permitir uma notação de código de caractere hexadecimal mais moderna :

"I said,\t\t\x22Can you hear me?\x22\n"
Sequência de fuga Unicode Caracteres literais colocados na string
\ 0 U + 0000 caractere nulo
(normalmente como um caso especial de notação octal \ ooo)
\uma U + 0007 alerta
\ b U + 0008 backspace
\ f U + 000C feed de formulário
\ n U + 000A feed de linha (ou nova linha em POSIX)
\ r U + 000D retorno de carro (ou nova linha no Mac OS 9 e anterior)
\ t U + 0009 aba horizontal
\ v U + 000B aba vertical
\ e U + 001B caractere de escape ( GCC , clang e tcc )
\você#### U + #### Caractere Unicode de 16 bits onde #### são quatro dígitos hexadecimais
\VOCÊ######## U + ####### Caractere Unicode de 32 bits onde ######## são oito dígitos hexadecimais (o espaço do caractere Unicode tem atualmente apenas 21 bits de largura, então os primeiros dois dígitos hexadecimais serão sempre zero)
\você{######} U + ####### Caractere Unicode de 21 bits, onde ###### é um número variável de dígitos hexadecimais
\ x ## U + 00 ## Especificação de caractere de 8 bits onde # é um dígito hexadecimal
\ ooo U + 0 ### Especificação de caracteres de 8 bits, onde o é um dígito octal
\ " U + 0022 citação dupla (")
\ & não-caractere usado para delimitar escapes numéricos em Haskell
\ ' U + 0027 citação única (')
\\ U + 005C barra invertida (\)
\? U + 003F ponto de interrogação (?)

Nota: Nem todas as sequências na lista são suportadas por todos os analisadores e pode haver outras sequências de escape que não estão na lista.

Escape aninhado

Quando o código em uma linguagem de programação é incorporado em outra, as strings incorporadas podem exigir vários níveis de escape. Isso é particularmente comum em expressões regulares e consultas SQL em outras linguagens ou outras linguagens em scripts de shell. Esse escape duplo costuma ser difícil de ler e criar.

Citação incorreta de strings aninhadas pode apresentar uma vulnerabilidade de segurança. O uso de dados não confiáveis, como em campos de dados de uma consulta SQL, deve usar instruções preparadas para evitar um ataque de injeção de código . Do PHP 2 ao 5.3, havia um recurso chamado aspas mágicas que escapavam automaticamente das strings (por conveniência e segurança), mas devido a problemas foi removido da versão 5.4 em diante.

Cordas brutas

Alguns idiomas fornecem um método para especificar que um literal deve ser processado sem qualquer interpretação específica do idioma. Isso evita a necessidade de escape e produz strings mais legíveis.

Strings brutas são particularmente úteis quando um caractere comum precisa ser escapado, notadamente em expressões regulares (aninhadas como strings literais), onde a barra invertida \é amplamente usada e em caminhos DOS / Windows , onde a barra invertida é usada como separador de caminho. A profusão de barras invertidas é conhecida como síndrome do palito de dente inclinado e pode ser reduzida com o uso de fios crus. Compare os nomes de caminho de escape e brutos em C #:

 "The Windows path is C:\\Foo\\Bar\\Baz\\"
 @"The Windows path is C:\Foo\Bar\Baz\"

Exemplos extremos ocorrem quando eles são combinados - os caminhos da Convenção de Nomenclatura Uniforme começam com \\e, portanto, uma expressão regular de escape correspondente a um nome UNC começa com 8 barras invertidas "\\\\\\\\", devido à necessidade de escapar da string e da expressão regular. Usar strings brutas reduz isso para 4 (escapando na expressão regular), como em C # @"\\\\".

Em documentos XML, as seções CDATA permitem o uso de caracteres como & e <sem que um analisador XML tente interpretá-los como parte da estrutura do próprio documento. Isso pode ser útil ao incluir texto literal e código de script, para manter o documento bem formado .

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

Literais de string multilinha

Em muitas linguagens, os literais de string podem conter novas linhas literais, abrangendo várias linhas. Como alternativa, novas linhas podem ser escapadas, na maioria das vezes como \n. Por exemplo:

echo 'foo
bar'

e

echo -e "foo\nbar"

são ambos bash válidos, produzindo:

foo
bar

As linguagens que permitem novas linhas literais incluem bash, Lua, Perl, PHP, R e Tcl. Em algumas outras linguagens, os literais de string não podem incluir novas linhas.

Dois problemas com literais de string de várias linhas são novas linhas à esquerda e à direita e recuo. Se os delimitadores iniciais ou finais estiverem em linhas separadas, haverá novas linhas extras, enquanto se não estiverem, o delimitador torna a string mais difícil de ler, especialmente para a primeira linha, que geralmente é recuada de maneira diferente do resto. Além disso, o literal não deve ter recuo, pois o espaço em branco inicial é preservado - isso interrompe o fluxo do código se o literal ocorrer dentro do código recuado.

A solução mais comum para esses problemas são os literais de string no estilo de documento . Falando formalmente, um documento here não é um literal de string, mas sim um literal de fluxo ou literal de arquivo. Eles se originam em scripts de shell e permitem que um literal seja alimentado como entrada para um comando externo. O delimitador de abertura é <<ENDonde ENDpode estar qualquer palavra, e o delimitador de fechamento está ENDem uma linha por si só, servindo como um limite de conteúdo - isso <<ocorre devido ao redirecionamento de stdin do literal. Como o delimitador é arbitrário, eles também evitam o problema de colisão do delimitador. Isso também permite que as guias iniciais sejam removidas por meio da sintaxe da variante, <<-ENDembora os espaços iniciais não sejam removidos. Desde então, a mesma sintaxe foi adotada para strings literais de várias linhas em várias linguagens, mais notavelmente Perl, e também são chamadas de documentos aqui, e mantêm a sintaxe, apesar de serem strings e não envolverem redirecionamento. Tal como acontece com outros literais de string, eles às vezes podem ter um comportamento especificado diferente, como a interpolação de variável.

Python, cujos literais de string usuais não permitem novas linhas literais, em vez disso tem uma forma especial de string, projetada para literais de várias linhas, chamada de aspas triplas . Eles usam um delimitador triplo, '''ou """. Esses literais são usados ​​especialmente para documentação embutida, conhecidos como docstrings .

Tcl permite quebras de linha literais em strings e não tem sintaxe especial para auxiliar em strings de várias linhas, embora os delimitadores possam ser colocados nas linhas por si próprios e novas linhas iniciais e finais removidas por string trim, enquanto string mappodem ser usados ​​para remover indentação.

Concatenação de literal de string

Algumas linguagens fornecem concatenação de literal de string , onde literais de string adjacentes são implicitamente unidos em um único literal em tempo de compilação. Este é um recurso de C, C ++, D, Ruby e Python, que o copiou de C. Notavelmente, essa concatenação acontece no tempo de compilação, durante a análise lexical (como uma fase após a tokenização inicial) e é contrastada com ambos os tempos de execução concatenação de string (geralmente com o +operador) e concatenação durante o dobramento constante , que ocorre no tempo de compilação, mas em uma fase posterior (após a análise de frase ou "análise"). A maioria das linguagens, como C #, Java e Perl, não oferece suporte à concatenação literal de string implícita e, em vez disso, exige concatenação explícita, como com o +operador (isso também é possível em D e Python, mas ilegal em C / C ++ - veja abaixo) ; neste caso, a concatenação pode acontecer em tempo de compilação, por meio de dobramento constante, ou pode ser adiada para o tempo de execução.

Motivação

Em C, onde o conceito e o termo se originam, a concatenação literal de string foi introduzida por dois motivos:

  • Para permitir que strings longas ocupem várias linhas com indentação adequada, em contraste com a continuação de linha, que destrói o esquema de indentação; e
  • Para permitir a construção de literais de string por macros (via stringizing ).

Em termos práticos, isso permite a concatenação de strings nas fases iniciais de compilação ("tradução", especificamente como parte da análise lexical), sem exigir análise de frase ou dobramento constante. Por exemplo, o seguinte é C / C ++ válido:

char *s = "hello, " "world";
printf("hello, " "world");

No entanto, os seguintes são inválidos:

char *s = "hello, " + "world";
printf("hello, " + "world");

Isso ocorre porque os literais de string têm tipo de matriz , (C) ou (C ++), que não pode ser adicionado; esta não é uma restrição na maioria dos outros idiomas. char [n]const char [n]

Isso é particularmente importante quando usado em combinação com o pré-processador C , para permitir que as strings sejam calculadas após o pré-processamento, particularmente em macros. Como um exemplo simples:

char *file_and_message = __FILE__ ": message";

irá (se o arquivo for chamado de ac) expandir para:

char *file_and_message = "a.c" ": message";

que é então concatenado, sendo equivalente a:

char *file_and_message = "a.c: message";

Um caso de uso comum é na construção de strings de formato printf ou scanf , em que os especificadores de formato são fornecidos por macros.

Um exemplo mais complexo usa a stringificação de inteiros (pelo pré-processador) para definir uma macro que se expande para uma sequência de literais de string, que são então concatenados em um único literal de string com o nome do arquivo e o número da linha:

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

Além dos requisitos sintáticos de C / C ++, a concatenação implícita é uma forma de açúcar sintático , tornando mais simples dividir literais de string em várias linhas, evitando a necessidade de continuação de linha (por meio de barras invertidas) e permitindo adicionar comentários a partes de strings. Por exemplo, em Python, pode-se comentar uma expressão regular desta forma:

re.compile("[A-Za-z_]"       # letter or underscore
           "[A-Za-z0-9_]*"   # letter, digit or underscore
          )

Problemas

A concatenação implícita de string não é exigida por compiladores modernos, que implementam dobragem constante e causa erros difíceis de detectar devido à concatenação não intencional por omitir uma vírgula, particularmente em listas verticais de strings, como em:

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

Conseqüentemente, ele não é usado na maioria das linguagens e foi proposto para desaprovação de D e Python. No entanto, remover o recurso quebra a compatibilidade com versões anteriores e substituí-lo por um operador de concatenação introduz problemas de precedência - a concatenação literal de string ocorre durante a lexing, antes da avaliação do operador, mas a concatenação por meio de um operador explícito ocorre ao mesmo tempo que outros operadores, portanto, a precedência é um problema, potencialmente exigindo parênteses para garantir a ordem de avaliação desejada.

Um problema mais sutil é que em C e C ++, existem diferentes tipos de literais de string e a concatenação deles tem um comportamento definido pela implementação, o que representa um risco potencial de segurança.

Diferentes tipos de cordas

Algumas linguagens fornecem mais de um tipo de literal, que têm comportamentos diferentes. Isso é particularmente usado para indicar strings brutas (sem escape) ou para desabilitar ou habilitar a interpolação de variáveis, mas tem outros usos, como distinguir conjuntos de caracteres. Na maioria das vezes, isso é feito alterando o caractere de citação ou adicionando um prefixo ou sufixo. Isso é comparável a prefixos e sufixos de literais inteiros , como para indicar números hexadecimais ou inteiros longos.

Um dos exemplos mais antigos é em scripts de shell, onde as aspas simples indicam uma string bruta ou "string literal", enquanto as aspas duplas têm sequências de escape e interpolação de variável.

Por exemplo, em Python , as strings brutas são precedidas por rou R- compare 'C:\\Windows'com r'C:\Windows'(embora uma string bruta Python não possa terminar com um número ímpar de barras invertidas). O Python 2 também distingue dois tipos de strings: strings ASCII ("bytes") de 8 bits (o padrão), explicitamente indicadas com um prefixo bou B, e strings Unicode, indicadas com um prefixo uou U. enquanto em Python 3 strings são Unicode por padrão e bytes são um bytestipo separado que, quando inicializado com aspas, deve ser prefixado com um b.

A notação do C # para strings brutas é chamada de @ -quoting.

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

Embora desative o escape, ele permite aspas duplas, o que permite representar aspas dentro da string:

@"I said, ""Hello there."""

C ++ 11 permite cadeias de caracteres brutas, cadeias de caracteres Unicode (UTF-8, UTF-16 e UTF-32) e cadeias de caracteres largas, determinadas por prefixos. Ele também adiciona literais para o C ++ existente string, que geralmente é preferido às strings de estilo C existentes.

Em Tcl, as strings delimitadas por chaves são literais, enquanto as strings delimitadas por aspas têm escape e interpolação.

Perl tem uma grande variedade de strings, que são consideradas mais formalmente como operadores, e são conhecidas como aspas e operadores semelhantes a aspas . Isso inclui uma sintaxe usual (delimitadores fixos) e uma sintaxe genérica, que permite a escolha de delimitadores; esses incluem:

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

REXX usa caracteres de sufixo para especificar caracteres ou strings usando seu código hexadecimal ou binário. Por exemplo,

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

todos produzem o caractere de espaço , evitando a chamada de função X2C(20).

Interpolação variável

Os idiomas diferem sobre se e como interpretar literais de string como 'bruto' ou 'variável interpolada'. A interpolação de variáveis ​​é o processo de avaliar uma expressão contendo uma ou mais variáveis ​​e retornar a saída onde as variáveis ​​são substituídas por seus valores correspondentes na memória. Em shells Unix compatíveis com sh (assim como Perl e Ruby), strings delimitadas por aspas (") são interpoladas, enquanto strings delimitadas por apóstrofo (') não. Por exemplo, o seguinte código Perl :

$name     = "Nancy";
$greeting = "Hello World";
print "$name said $greeting to the crowd of people.";

produz a saída:

Nancy said Hello World to the crowd of people.

O caractere sigilo ($) é interpretado para indicar interpolação de variável.

Da mesma forma, a printffunção produz a mesma saída usando notações como:

printf "%s said %s to the crowd of people.", $name, $greeting;

Os metacaracteres (% s) indicam interpolação de variável.

Isso é contrastado com strings "brutas":

print '$name said $greeting to the crowd of people.';

que produzem resultados como:

$name said $greeting to the crowd of people.

Aqui, os caracteres $ não são sigilos e não são interpretados como tendo qualquer significado diferente de texto simples.

Incorporação de código-fonte em literais de string

Linguagens que carecem de flexibilidade na especificação de literais de string tornam particularmente complicado escrever código de programação que gere outro código de programação. Isso é particularmente verdadeiro quando a linguagem de geração é a mesma ou semelhante à linguagem de saída.

Por exemplo:

  • escrever código para produzir quines
  • gerar uma linguagem de saída de dentro de um modelo da web ;
  • usando XSLT para gerar XSLT ou SQL para gerar mais SQL
  • gerar uma representação PostScript de um documento para fins de impressão, de dentro de um aplicativo de processamento de documentos escrito em C ou alguma outra linguagem.
  • escrever shaders

No entanto, algumas linguagens são particularmente bem adaptadas para produzir esse tipo de saída auto-similar, especialmente aquelas que oferecem suporte a várias opções para evitar a colisão de delimitadores.

Usar literais de string como código que gera outro código pode ter implicações de segurança adversas, especialmente se a saída for baseada, pelo menos parcialmente, na entrada de usuário não confiável. Isso é particularmente grave no caso de aplicativos baseados na Web, em que usuários mal-intencionados podem aproveitar essas fraquezas para subverter a operação do aplicativo, por exemplo, montando um ataque de injeção de SQL .

Veja também

Notas

Referências

links externos