Articulo de referencia

Literal de cadena

Una cadena literal o cadena anónima es una representación literal de un valor de cadena en el código fuente . Generalmente, un lenguaje de programación incluye una estructura de...

Una cadena literal o cadena anónima es una representación literal de un valor de cadena en el código fuente . Generalmente, un lenguaje de programación incluye una estructura de código para cadenas literales, que consiste en una serie de caracteres entre corchetes , normalmente comillas. En muchos lenguajes, el texto "foo"es una cadena literal que codifica el texto, foopero existen muchas otras variaciones.

Sintaxis

delimitado por corchetes

Una cadena literal entre corchetes está delimitada por un carácter de inicio y un carácter de fin. El lenguaje puede especificar el uso de cualquier carácter como delimitador.

Las comillas son la forma más común de delimitar una cadena literal. Muchos lenguajes admiten comillas dobles (p. ej., "Hello") y/o comillas simples (p. ej., 'there'). Cuando se admiten ambas, la colisión de delimitadores se puede minimizar tratando un estilo de comillas como texto normal cuando está encerrado entre comillas del otro estilo. En Python, el literal "Dwayne 'the rock' Johnson"es válido ya que las comillas exteriores son dobles, lo que hace que las comillas simples interiores sean texto normal.

Una cadena vacía se escribe como ""o ''.

Los delimitadores emparejados son dos tipos diferentes de caracteres, uno utilizado al principio de un literal y el otro al final. Con los delimitadores emparejados, el lenguaje puede admitir la inserción de comillas en el texto literal , siempre que estén emparejadas y no se salgan parcialmente de su propio ámbito. Por ejemplo, PostScript utiliza paréntesis, como en (The quick (brown fox))y m4 , utiliza acento grave` al principio y apóstrofe' al final. Tcl permite tanto comillas como llaves, como en "The quick brown fox"o {The quick {brown fox}}; esto deriva de las comillas simples en los shells de Unix y del uso de llaves en C para sentencias compuestas, ya que los bloques de código son sintácticamente lo mismo en Tcl que los literales de cadena; que los delimitadores estén emparejados es esencial para que esto sea factible.

Las citas se suelen realizar mediante comillas simples, pero algunas herramientas y conjuntos de caracteres admiten comillas dobles. Las comillas simples son aquellas que no tienen variantes únicas para la comilla izquierda y la derecha, como ""o ''. El conjunto de caracteres Unicode incluye versiones dobles:

"¡Hola!" '¡Hola!' "¡Hola!" "¡Hola!"

Mezcla de alcance

La mezcla de ámbitos es cuando los ámbitos se mezclan en lugar de ser puramente jerárquicos . [ a ]

En otras palabras, la "mezcla de ámbitos" se produce cuando no existe un delimitador de inicio inequívoco (o un delimitador de final inequívoco).

Ejemplos de una cita que se sale de su propio ámbito (que son cadenas no válidas) serían:

  • "InsideTheOuterString 'InnerString_ButWithUnmatchedEndingSingleQuoteThatRendersThisStringInvalid" ErroneousStringThatIsSomehowInsideTheInnerStringYetNotInsideTheOuterString'
  • "1 '2" 3'
  • "Inside1 'InsideBoth1and2" Inside2'

Los literales de cadena no permiten la mezcla de ámbitos, ya que crea programas ambiguos. Un literal de cadena a veces puede parecer que tiene ámbitos mixtos, pero existen reglas de precedencia de operadores [ b ] establecidas para cada lenguaje de programación específico para evitar la ambigüedad, como la táctica de leer las expresiones desde el carácter más a la izquierda hasta el más a la derecha, lo que otorga a un "símbolo de la izquierda una mayor precedencia (es decir, prioridad) sobre cualquier otra comilla que aparezca después (en la misma línea).

Como se mencionó anteriormente, las comillas anidadas pueden ser válidas, como en "Dwayne 'the rock' Johnson", pero requieren algún método que emplee una jerarquía (normalmente una estructura de datos de pila ), independientemente de si esa jerarquía utiliza caracteres delimitadores únicos , caracteres de escape o delimitadores de caracteres repetidos .

La "mezcla de ámbitos" es un caso específico de colisión de delimitadores, que se explica más adelante en esta página.

Espacios en blanco delimitados

Un lenguaje puede admitir cadenas de varias líneas. En YAML , los literales de cadena se pueden especificar mediante la posición relativa de los espacios en blanco y la sangría.

- título : Un ejemplo de cadena multilínea en YAML cuerpo : | Esta es una cadena multilínea. Pueden aparecer aquí metacaracteres "especiales" . La extensión de esta cadena está representada por la sangría.

Delimitado por palabras

Algunos lenguajes, como Perl y PHP, permiten literales de cadena que se delimitan igual que las palabras en un lenguaje natural . En el siguiente código Perl, por ejemplo, red, green, y blueson literales de cadena, aunque no estén entre comillas:

%map = ( rojo => 0x00f , azul => 0x0f0 , verde => 0xf00 );

En la mayoría de los casos, Perl trata una secuencia de caracteres alfanuméricos no reservados como una cadena literal. Por ejemplo, las siguientes dos líneas de Perl son equivalentes:

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

Notación declarativa

La longitud de un literal se puede codificar al principio del texto, lo que elimina la necesidad de marcar el inicio y el final de una cadena. Por ejemplo, en FORTRAN , los literales de cadena se escribían en notación Hollerith , donde un recuento decimal del número de caracteres iba seguido de la letra H y, a continuación, de los caracteres de la cadena.

35 Ejemplo de cadena literal de Hollerith de HAn

Una desventaja de esta técnica es que es relativamente propensa a errores a menos que la inserción de longitud esté automatizada, especialmente para codificaciones multibyte. Las ventajas incluyen: reduce la necesidad de buscar el delimitador final y, por lo tanto, requiere menos sobrecarga computacional ; previene problemas de colisión de delimitadores y permite la inclusión de metacaracteres que de otro modo podrían confundirse con comandos.

Colisión de delimitadores

Al usar comillas, si se desea representar el delimitador en sí mismo en un literal de cadena, se presenta el problema de la colisión de delimitadores . Por ejemplo, si el delimitador es una comilla doble, no se puede representar simplemente una comilla doble en sí misma mediante el literal, """ya que la segunda comilla se interpreta como el final del literal de cadena, no como el valor de la cadena, y de manera similar no se puede escribir "This is "in quotes", but invalid."ya que la parte entre comillas del medio se interpreta como fuera de las comillas. Existen varias soluciones, la más general de las cuales es el uso de secuencias de escape, como "\""o "This is \"in quotes\" and properly escaped.", pero hay muchas otras soluciones.

Las comillas emparejadas, como las llaves en Tcl, permiten cadenas anidadas, como {foo {bar} zork}pero no resuelven el problema de la colisión de delimitadores, ya que un delimitador de cierre desequilibrado no puede simplemente incluirse, como en {}}.

Duplicar

Varios lenguajes, incluidos Pascal , BASIC , DCL , Smalltalk , SQL , J y Fortran , evitan la colisión de delimitadores duplicando las comillas que se pretenden que formen parte del literal de cadena en sí:

'Esta cadena de Pascal '' contiene dos apóstrofes '' '
"Le dije: "¿Puedes oírme?""

Cotización doble

Algunos lenguajes, como Fortran , Modula-2 , JavaScript , Python y PHP, permiten más de un delimitador de comillas; cuando hay dos delimitadores posibles, se habla de comillas dobles . Normalmente, esto permite al programador usar comillas simples o dobles indistintamente: cada literal debe usar una u otra.

"Esta es la manzana de John." "Le dije: "¿Puedes oírme?"

Sin embargo, esto no permite tener un único literal con ambos delimitadores. Esto se puede solucionar utilizando varios literales y la concatenación de cadenas :

'Dije: "Esta es la manzana de John ."'

Python tiene concatenación de literales de cadena , por lo que los literales de cadena consecutivos se concatenan incluso sin un operador, por lo que esto se puede reducir a:

'Dije: "Esta es la manzana de John ."'

Delimitador de citas

C++11 introdujo los llamados literales de cadena sin formato . Consisten, esencialmente en:

R" end-of-string-id ( content ) end-of-string-id ",

Es decir, después de que R"el programador puede ingresar hasta 16 caracteres excepto espacios en blanco, paréntesis o barra invertida, que forman el identificador de fin de cadena (su propósito es repetirse para señalar el final de la cadena, eos id para abreviar), luego se requiere un paréntesis de apertura (para denotar el final del eos id). Luego sigue el contenido real del literal: se pueden usar cualquier secuencia de caracteres (excepto que no puede contener un paréntesis de cierre seguido del eos id seguido de una comilla), y finalmente, para terminar la cadena, se requiere un paréntesis de cierre, el eos id y una comilla. El caso más simple de dicho literal es con contenido vacío y eos id vacío: R"()". El eos id puede contener comillas: es un literal válido (el eos id está aquí). Las secuencias de escape no funcionan en literales de cadena sin formato.R""(I asked, "Can you hear me?")"""

D admite algunos delimitadores de comillas, con cadenas que comienzan con q"más un delimitador de apertura y terminan con el delimitador de cierre respectivo y ". Los pares de delimitadores disponibles son (), <>, {}, y []; un delimitador no identificador no emparejado es su propio delimitador de cierre. Los delimitadores emparejados se anidan, por lo que es un literal válido; un ejemplo con el carácter q"(A pair "()" of parens in quotes)"no anidado es . De forma similar a C++11, D permite literales de estilo documento aquí con identificadores de fin de cadena:/q"/I asked, "Can you hear me?"/"

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

En D, el identificador de fin de cadena debe ser un identificador (caracteres alfanuméricos).

En algunos lenguajes de programación, como sh y Perl , existen diferentes delimitadores que se tratan de manera distinta, por ejemplo, interpolando o no las cadenas, por lo que se debe tener cuidado al elegir qué delimitador usar; consulte la sección sobre diferentes tipos de cadenas a continuación.

Citas múltiples

Otra extensión consiste en el uso de comillas múltiples , lo que permite al autor elegir qué caracteres deben especificar los límites de una cadena literal.

Por ejemplo, en Perl :

qq^Dije: "¿Puedes oírme?"^ qq@Dije: "¿Puedes oírme?"@ qq§Dije: "¿Puedes oírme?"§

Todos producen el resultado deseado. Si bien esta notación es más flexible, pocos lenguajes la admiten; además de Perl, Ruby (influenciado por Perl) y C++11 también la admiten. Una variante de las comillas múltiples es el uso de cadenas al estilo de los documentos .

Lua (a partir de la versión 5.1) proporciona una forma limitada de comillas múltiples, particularmente para permitir el anidamiento de comentarios largos o cadenas incrustadas. Normalmente se usan ` [[&` ]]para delimitar cadenas literales (se elimina el salto de línea inicial, de lo contrario se deja en blanco), pero los corchetes de apertura pueden incluir cualquier número de signos de igual, y solo los corchetes de cierre con el mismo número de signos cierran la cadena. Por ejemplo:

local ls = [=[ Esta notación se puede usar para rutas de Windows: ruta local = [[C:\Windows\Fonts]] ]=]

El uso de múltiples comillas es particularmente útil con expresiones regulares que contienen delimitadores habituales como las comillas, ya que esto evita tener que escaparlas. Un ejemplo temprano es sed , donde en el comando de sustitución los delimitadores de barra diagonal predeterminados se pueden reemplazar por otro carácter, como en .s/regex/replacement//s,regex,replacement,

Funciones constructoras

Otra opción, poco frecuente en lenguajes modernos, consiste en utilizar una función para construir una cadena, en lugar de representarla mediante un literal. Generalmente, esto no se usa en lenguajes modernos porque el cálculo se realiza en tiempo de ejecución, no en tiempo de análisis sintáctico.

Por ejemplo, las primeras versiones de BASIC no incluían secuencias de escape ni ninguna otra solución alternativa de las que se enumeran aquí, por lo que era necesario utilizar la CHR$función, que devuelve una cadena que contiene el carácter correspondiente a su argumento. En ASCII, la comilla tiene el valor 34, por lo que para representar una cadena con comillas en un sistema ASCII se escribiría

"Dije, " + CHR$ ( 34 ) + "¿Puedes oírme?" + CHR$ ( 34 )

En C, se dispone de una funcionalidad similar mediante sprintfel %cespecificador de formato "character", aunque en presencia de otras soluciones alternativas, generalmente no se utiliza:

char buffer [ 32 ]; snprintf ( buffer , sizeof buffer , "Esto es %cin quotes.%c" , 34 , 34 );

Estas funciones constructoras también pueden usarse para representar caracteres no imprimibles, aunque generalmente se utilizan secuencias de escape. En C++ se puede emplear una técnica similar con el std::stringoperador de conversión a cadena.

Secuencias de escape

Las secuencias de escape son una técnica general para representar caracteres que de otro modo serían difíciles de representar directamente, incluidos los delimitadores, los caracteres no imprimibles (como los retrocesos), los saltos de línea y los caracteres de espacio en blanco (que de otro modo serían imposibles de distinguir visualmente), y tienen una larga historia. Por consiguiente, se utilizan ampliamente en literales de cadena, y agregar una secuencia de escape (ya sea a un solo carácter o a lo largo de una cadena) se conoce como escape .

Se elige un carácter como prefijo para codificar caracteres que son difíciles o imposibles de incluir directamente. Lo más común es la barra invertida ; además de otros caracteres, un punto clave es que la barra invertida en sí misma se puede codificar como una doble barra invertida \\y, para cadenas delimitadas, el delimitador en sí se puede codificar mediante escape, por ejemplo, con \"para ". Una expresión regular para dichas cadenas con escape se puede dar de la siguiente manera, como se encuentra en la especificación ANSI C : [ 1 ] [ c ]

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

significa "una comilla; seguida de cero o más caracteres de escape (barra invertida seguida de algo, posiblemente barra invertida o comilla), o un carácter que no sea de escape ni de comilla; terminando en una comilla" – el único problema es distinguir la comilla de cierre de una comilla precedida por una barra invertida, que a su vez puede ser de escape. Varios caracteres pueden seguir a la barra invertida, como \uFFFF, dependiendo del esquema de escape.

Una cadena escapada debe ser analizada léxicamente , convirtiéndose así en la cadena original que representa. Esto se realiza durante la fase de evaluación del análisis léxico general del lenguaje de programación: el evaluador del analizador léxico del lenguaje ejecuta su propio analizador léxico para los literales de cadena escapada.

Entre otras cosas, debe ser posible codificar el carácter que normalmente finaliza la cadena constante, además de que debe existir alguna forma de especificar el carácter de escape. Las secuencias de escape no siempre son elegantes ni fáciles de usar, por lo que muchos compiladores también ofrecen otros medios para resolver los problemas comunes. Sin embargo, las secuencias de escape resuelven cualquier problema de delimitación y la mayoría de los compiladores las interpretan. Cuando un carácter de escape se encuentra dentro de un literal de cadena, significa "este es el inicio de la secuencia de escape". Cada secuencia de escape especifica un carácter que se colocará directamente en la cadena. El número real de caracteres necesarios en una secuencia de escape varía. El carácter de escape se encuentra en la parte superior izquierda del teclado, pero el editor lo traducirá, por lo que no se puede insertar directamente en una cadena. La barra invertida se utiliza para representar el carácter de escape en un literal de cadena.

Muchos lenguajes admiten el uso de metacaracteres dentro de literales de cadena. Los metacaracteres tienen diferentes interpretaciones según el contexto y el lenguaje, pero generalmente son una especie de "comando de procesamiento" para representar caracteres imprimibles o no imprimibles.

Por ejemplo, en una cadena literal de C, si la barra invertida va seguida de una letra como "b", "n" o "t", esto representa un carácter no imprimible de retroceso , salto de línea o tabulación , respectivamente. O si la barra invertida va seguida de 1 a 3 dígitos octales , esta secuencia se interpreta como la unidad de código arbitraria con el valor especificado en la codificación del literal (por ejemplo, el código ASCII correspondiente para un literal ASCII). Posteriormente, esto se amplió para permitir la notación de códigos de caracteres hexadecimales más moderna .

" Dije: ¿Puedes oírme ?

Nota: No todas las secuencias de la lista son compatibles con todos los analizadores sintácticos, y puede haber otras secuencias de escape que no estén en la lista.

Escape anidado

Cuando se inserta código de un lenguaje de programación dentro de otro, las cadenas incrustadas pueden requerir varios niveles de escape. Esto es particularmente común en expresiones regulares y consultas SQL dentro de otros lenguajes, o en otros lenguajes dentro de scripts de shell. Este doble escape suele ser difícil de leer y escribir.

El uso incorrecto de comillas en cadenas anidadas puede representar una vulnerabilidad de seguridad. Al utilizar datos no confiables, como en los campos de datos de una consulta SQL, se deben usar sentencias preparadas para prevenir ataques de inyección de código . En PHP 2 a 5.3, existía una función llamada comillas mágicas que escapaba automáticamente las cadenas (por comodidad y seguridad), pero debido a problemas, se eliminó a partir de la versión 5.4.

cuerdas crudas

Algunos idiomas ofrecen un método para especificar que un literal debe procesarse sin ninguna interpretación específica del idioma. Esto evita la necesidad de usar caracteres de escape y produce cadenas más legibles.

Las cadenas sin formato son particularmente útiles cuando se necesita escapar un carácter común, especialmente en expresiones regulares (anidadas como literales de cadena), donde la barra invertida \se usa ampliamente, y en rutas de DOS/Windows , donde se usa como separador de ruta. La profusión de barras invertidas se conoce como síndrome del palillo inclinado y se puede reducir usando cadenas sin formato. Compare las rutas con y sin formato en C#:

"La ruta de Windows es C:\\Foo\\Bar\\Baz\\" @"La ruta de Windows es C:\Foo\Bar\Baz\"

Los ejemplos extremos ocurren cuando se combinan: las rutas de la Convención de Nombres Uniformes comienzan con \\, y por lo tanto, una expresión regular escapada que coincida con un nombre UNC comienza con 8 barras invertidas, "\\\\\\\\", debido a la necesidad de escapar la cadena y la expresión regular. El uso de cadenas sin formato reduce esto a 4 (escapando en la expresión regular), como en C# @"\\\\".

En los documentos XML, las secciones CDATA permiten el uso de caracteres como & y < sin que un analizador XML intente interpretarlos como parte de la estructura del documento. Esto puede ser útil al incluir texto literal y código de scripting, para mantener el documento bien formado .

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

Literales de cadena multilínea

En muchos lenguajes, las cadenas literales pueden contener saltos de línea literales que abarcan varias líneas. Alternativamente, los saltos de línea se pueden escapar, generalmente como \n. Por ejemplo:

eco 'foo bar'

y

echo -e "foo\nbar"

Ambas son sentencias BASH válidas y ambas producen el mismo resultado:

comida bar

Los lenguajes que permiten saltos de línea literales incluyen BASH , Lua , Perl , PHP , R y Tcl . En otros lenguajes, los literales de cadena no pueden incluir saltos de línea.

Dos problemas con las cadenas literales multilínea son los saltos de línea iniciales y finales, y la indentación. Si los delimitadores inicial y final se encuentran en líneas separadas, se generan saltos de línea adicionales; si no, el delimitador dificulta la lectura de la cadena, especialmente en la primera línea, que suele tener una indentación diferente a la del resto. Además, la cadena literal debe estar sin indentar, ya que se conservan los espacios en blanco iniciales; esto interrumpe el flujo del código si la cadena literal aparece dentro de código indentado.

La solución más común para estos problemas son los literales de cadena estilo documento here . Formalmente hablando, un documento here no es un literal de cadena, sino un literal de flujo o un literal de archivo. Estos se originan en scripts de shell y permiten que un literal se pase como entrada a un comando externo. El delimitador de apertura es donde puede ser cualquier palabra, y el delimitador de cierre está en una línea aparte, sirviendo como límite de contenido; el se debe a la redirección de stdin desde el literal. Debido a que el delimitador es arbitrario, estos también evitan el problema de la colisión de delimitadores. Estos también permiten eliminar tabulaciones iniciales mediante la sintaxis variante, aunque los espacios iniciales no se eliminan. La misma sintaxis se ha adoptado desde entonces para literales de cadena multilínea en varios lenguajes, sobre todo Perl, y también se les conoce como documentos here, y conservan la sintaxis, a pesar de ser cadenas y no implicar redirección. Al igual que con otros literales de cadena, estos a veces pueden tener un comportamiento diferente especificado, como la interpolación de variables.<<ENDENDEND<<<<-END

Python, cuyos literales de cadena habituales no permiten saltos de línea literales, tiene en su lugar una forma especial de cadena, diseñada para literales multilínea, llamada comillas triples . Estas usan un delimitador triple, ya sea '''o """. Estos literales se usan especialmente para la documentación en línea, conocida como docstrings .

Tcl permite saltos de línea literales en cadenas y no tiene sintaxis especial para ayudar con cadenas de varias líneas, aunque los delimitadores se pueden colocar en líneas por sí solos y los saltos de línea iniciales y finales se pueden eliminar mediante string trim, mientras que string mapse puede usar para eliminar la sangría.

concatenación literal de cadena

Algunos lenguajes proporcionan concatenación de literales de cadena , donde los literales de cadena adyacentes se unen implícitamente en un solo literal en tiempo de compilación. Esta es una característica de C, [ 7 ] [ 8 ] C++, [ 9 ] D, [ 10 ] Ruby, [ 11 ] y Python, [ 12 ] que la copió de C. [ 13 ] Cabe destacar que esta concatenación ocurre en tiempo de compilación, durante el análisis léxico (como una fase posterior a la tokenización inicial), y se contrasta con la concatenación de cadenas en tiempo de ejecución (generalmente con el +operador) [ 14 ] y la concatenación durante el plegado de constantes , que ocurre en tiempo de compilación, pero en una fase posterior (después del análisis de frases o "parsing"). La mayoría de los lenguajes, como C#, Java [ 15 ] y Perl, no admiten la concatenación implícita de literales de cadena, y en su lugar requieren la concatenación explícita, como con el +operador (esto también es posible en D y Python, pero ilegal en C/C++ – ver más abajo); En este caso, la concatenación puede ocurrir en tiempo de compilación, mediante la reducción de constantes, o puede posponerse hasta el tiempo de ejecución.

Motivación

En C, donde se originan el concepto y el término, la concatenación de literales de cadena se introdujo por dos razones: [ 16 ]

  • Para permitir que las cadenas largas abarquen varias líneas con la indentación adecuada, a diferencia de la continuación de línea, que destruye el esquema de indentación; y
  • Para permitir la construcción de literales de cadena mediante macros (a través de la conversión a cadena ). [ 17 ]

En términos prácticos, esto permite la concatenación de cadenas en las primeras fases de la compilación ("traducción", específicamente como parte del análisis léxico), sin necesidad de análisis de frases ni plegado de constantes. Por ejemplo, el siguiente código C es válido:

char s [] = "hola, " "mundo" ; printf ( "hola, " "mundo" );

Sin embargo, lo siguiente no es válido:

char s [] = "hola, " + "mundo" ; printf ( "hola, " + "mundo" );

Esto se debe a que los literales de cadena tienen un tipo de matriz ( char[]C) o const char[](C++), que no se puede sumar; esta no es una restricción en la mayoría de los demás lenguajes. Tenga en cuenta que operator+está sobrecargado para literales de cadena en C++.

Esto es particularmente importante cuando se usa en combinación con el preprocesador de C , para permitir que las cadenas se calculen después del preprocesamiento, especialmente en macros. [ 13 ] Como ejemplo sencillo:

char archivo_y_mensaje [] = __ARCHIVO__ ": mensaje" ;

se expandirá (si el archivo se llama ac) a:

char archivo_y_mensaje [] = "ac" ": mensaje" ;

que luego se concatena, siendo equivalente a:

char archivo_y_mensaje [] = "ac: mensaje" ;

Un caso de uso común es en la construcción printf()de scanf()cadenas de formato , donde los especificadores de formato se dan mediante macros. [ 18 ] [ 19 ]

Un ejemplo más complejo utiliza la conversión a cadena de enteros (por el preprocesador) para definir una macro que se expande a una secuencia de literales de cadena, que luego se concatenan a un único literal de cadena con el nombre del archivo y el número de línea: [ 20 ]

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

Más allá de los requisitos sintácticos de C/C++, la concatenación implícita es una forma de azúcar sintáctico , que simplifica la división de literales de cadena en varias líneas, evitando la necesidad de continuación de línea (mediante barras invertidas) y permitiendo agregar comentarios a partes de las cadenas. Por ejemplo, en Python, se puede comentar una expresión regular de esta manera: [ 21 ]

importar re desde re importar Patrónpatrón : Patrón = re.compile ( "[A-Za-z_]" # letra o guion bajo " [ A-Za-z0-9_]*" # letra, dígito o guion bajo )

Problemas

La concatenación implícita de cadenas no es requerida por los compiladores modernos, que implementan el plegado de constantes, y causa errores difíciles de detectar debido a la concatenación involuntaria por omisión de una coma, particularmente en listas horizontales de cadenas, como en:

l : lista [ str ] = [ "foo" , "bar" "zork" ]

En consecuencia, no se utiliza en la mayoría de los lenguajes y se ha propuesto su desuso en D [ 22 ] y Python [ 13 ] . Sin embargo, eliminar la característica rompe la compatibilidad con versiones anteriores, y reemplazarla con un operador de concatenación introduce problemas de precedencia: la concatenación de literales de cadena ocurre durante el análisis léxico, antes de la evaluación del operador, pero la concatenación mediante un operador explícito ocurre al mismo tiempo que otros operadores, por lo que la precedencia es un problema, lo que potencialmente requiere paréntesis para garantizar el orden de evaluación deseado.

Un problema más sutil es que en C y C++, [ 23 ] existen diferentes tipos de literales de cadena, y la concatenación de estos tiene un comportamiento definido por la implementación, lo que plantea un riesgo potencial de seguridad. [ 24 ]

Diferentes tipos de cuerdas

Algunos lenguajes ofrecen más de un tipo de literal, con comportamientos distintos. Esto se utiliza especialmente para indicar cadenas sin formato (sin escape) o para habilitar o deshabilitar la interpolación de variables, pero también tiene otros usos, como distinguir conjuntos de caracteres. Generalmente, esto se logra cambiando el carácter de comillas o añadiendo un prefijo o sufijo. Esto es comparable a los prefijos y sufijos que se usan en los literales enteros , como para indicar números hexadecimales o enteros largos.

Uno de los ejemplos más antiguos se encuentra en los scripts de shell, donde las comillas simples indican una cadena sin formato o "cadena literal", mientras que las comillas dobles contienen secuencias de escape e interpolación variable.

Por ejemplo, en Python , las cadenas sin formato van precedidas de un ro R– compárese 'C:\\Windows'con r'C:\Windows'(aunque una cadena sin formato de Python no puede terminar en un número impar de barras invertidas). Python 2 también distingue dos tipos de cadenas: cadenas ASCII de 8 bits ("bytes") (el valor predeterminado), indicadas explícitamente con un prefijo bo B, y cadenas Unicode, indicadas con un prefijo uo . [ 25 ] mientras que en Python 3 las cadenas son Unicode por defecto y los bytes son un tipo separado que cuando se inicializan con comillas deben ir precedidos de un .Ubytesb

La notación de C# para cadenas sin formato se llama comillas con @.

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

Si bien esto desactiva el escape, permite el uso de comillas dobles, lo que permite representar comillas dentro de la cadena:

"Dije: "Hola.""

C++11 permite cadenas sin formato, cadenas Unicode (UTF-8, UTF-16 y UTF-32) y cadenas de caracteres anchos, determinadas por prefijos. También añade literales para las cadenas existentes de C++ string, que generalmente se prefieren a las cadenas de estilo C existentes.

En Tcl, las cadenas delimitadas por llaves son literales, mientras que las cadenas delimitadas por comillas tienen caracteres de escape e interpolación.

Perl tiene una amplia variedad de cadenas, que se consideran más formalmente operadores, y se conocen como operadores de comillas y operadores similares a comillas . Estos incluyen tanto una sintaxis usual (delimitadores fijos) como una sintaxis genérica, que permite elegir delimitadores. Estos incluyen: [ 26 ]

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

REXX utiliza caracteres de sufijo para especificar caracteres o cadenas utilizando su código hexadecimal o binario. Por ejemplo:

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

todos generan el carácter de espacio , evitando la llamada a la función X2C(20).

interpolación de cadenas

En algunos lenguajes, las cadenas literales pueden contener marcadores de posición que hacen referencia a variables o expresiones del contexto actual , las cuales se evalúan (generalmente en tiempo de ejecución). Esto se conoce como interpolación de variables o, más comúnmente, interpolación de cadenas . Los lenguajes que admiten la interpolación suelen distinguir entre las cadenas literales interpoladas y las que no lo son. Por ejemplo, en los shells Unix compatibles con sh (así como en Perl y Ruby), las cadenas entre comillas dobles (delimitadas por comillas simples, ") se interpolan, mientras que las cadenas entre comillas simples (delimitadas por apóstrofes simples, ' ) no lo son. A los literales de cadena no interpolados a veces se les denomina "cadenas sin procesar", pero esto es distinto de "cadena sin procesar" en el sentido de escape. Por ejemplo, en Python, una cadena con prefijo ro Rse llama cadena sin procesar y no tiene escape ni interpolación, [ 27 ] una cadena normal (sin prefijo) tiene escape pero no interpolación, [ 28 ] y una cadena con prefijo fo Fse llama f-cadena [ 29 ] y tiene escape [ 30 ] e interpolación. [ 31 ]

Por ejemplo, el siguiente código Perl :

$name = "Nancy" ; $greeting = "Hola Mundo" ; print "$name dijo $greeting a la multitud de gente." ;

produce el siguiente resultado:

Nancy saludó al mundo con un "Hola, mundo" a la multitud.

En este caso, el carácter metacaracter ($) (que no debe confundirse con el símbolo en la instrucción de asignación de variables) se interpreta para indicar interpolación de variables y requiere algún tipo de escape si necesita ser mostrado literalmente.

Esto debe contrastarse con la printffunción, que produce el mismo resultado utilizando notación como:

printf "%s dijo %s a la multitud de gente." , $name , $greeting ;

pero no realiza interpolación: es %sun marcador de posición en una cadena de formato printf , pero las variables en sí están fuera de la cadena.

Esto contrasta con las cadenas "en bruto":

print '$name dijo $saludo a la multitud de gente.' ;

que producen resultados como:

$name dijo $saludando a la multitud de gente.

Aquí, los caracteres $ no son metacaracteres y no se interpretan con ningún significado más allá del texto plano.

Incrustar código fuente en literales de cadena

Los lenguajes que carecen de flexibilidad para especificar literales de cadena dificultan especialmente la escritura de código que genera otro código. Esto es particularmente cierto cuando el lenguaje de generación es igual o similar al lenguaje de salida.

Por ejemplo:

  • escribir código para producir quinos
  • generar un lenguaje de salida desde dentro de una plantilla web ;
  • usar XSLT para generar XSLT, o SQL para generar más SQL
  • Generar una representación PostScript de un documento para su impresión, desde una aplicación de procesamiento de documentos escrita en C u otro lenguaje.

Sin embargo, algunos lenguajes están particularmente bien adaptados para producir este tipo de resultados autosimilares, especialmente aquellos que admiten múltiples opciones para evitar la colisión de delimitadores.

El uso de literales de cadena como código que genera otro código puede tener consecuencias negativas para la seguridad, especialmente si la salida se basa, al menos parcialmente, en datos de entrada de usuario no confiables. Esto es particularmente grave en el caso de aplicaciones web, donde usuarios malintencionados pueden aprovechar estas vulnerabilidades para sabotear el funcionamiento de la aplicación, por ejemplo, mediante un ataque de inyección SQL .

Véase también

Notas

  1. El alcance "mezclado" puede pensarse como las partes de un diagrama de Venn que sobresalen (es decir, las partes que no se comparten). El alcance jerárquico puede pensarse como una muñeca rusa o un conjunto de círculos concéntricos .
  2. Es decir, reglas de orden de operaciones, similares a PEMDAS , pero hechas específicamente para programación en lugar de matemáticas generales, como^a veces representa XOR bit a bit o StartOfString_RegEx (dependiendo del contexto) en programación, pero representa AND o ExponentPower (de nuevo, dependiente del contexto) en matemáticas.
  3. La expresión regular que se muestra aquí no está entrecomillada ni escapada, para reducir la confusión.
  4. 1 2 Dado que esta secuencia de escape representa una unidad de código específica en lugar de un carácter específico, el punto de código (si lo hay) que representa depende de la codificación del literal de cadena en el que se encuentra.

Referencias

  1. "Gramática ANSI C, especificación Lex" . liu.se. Consultado el 29 de junio de 2026 .
  2. 1 2 "Apéndice B. Caracteres, cadenas y reglas de escape" . realworldhaskell.org . Consultado el 22 de junio de 2016 .
  3. 1 2 "Cadena" . mozilla.org . Consultado el 22 de junio de 2016 .
  4. 1 2 3 4 5 6 7 8 9 10 11 12 13 "Secuencias de escape (C)" . microsoft.com . Consultado el 22 de junio de 2016 .
  5. 1 2 "Fundamentos del estándar internacional - Lenguajes de programación - C" (PDF) . 5.10. Abril de 2003. pp. 52, 153–154 , 159. Archivado (PDF) del original el 6 de junio de 2016. Recuperado el 17 de octubre de 2010 . 
  6. "6.35 El carácter <ESC> en constantes" , Manual de GCC 4.8.2 , consultado el 8 de marzo de 2014.
  7. Borrador de norma C11 , Borrador del Comité WG14 N1570 — 12 de abril de 2011 , 5.1.1.2 Fases de traducción, pág. 11: "6. Los tokens literales de cadena adyacentes se concatenan."
  8. Sintaxis de C: Concatenación de literales de cadena
  9. Borrador del estándar C++11 , "Borrador de trabajo, estándar para el lenguaje de programación C++" (PDF) ., 2.2 Fases de traducción [lex.phases], pág. 17: "6. Se concatenan los tokens literales de cadena adyacentes." y 2.14.5 Literales de cadena [lex.string], nota 13, págs. 28-29: "En la fase de traducción 6 (2.2), se concatenan los literales de cadena adyacentes."
  10. Lenguaje de programación D , Análisis léxico , "Literales de cadena": "Las cadenas adyacentes se concatenan con el operador ~ o por simple yuxtaposición:"
  11. ruby: El lenguaje de programación Ruby , Lenguaje de programación Ruby, 19/10/2017 , consultado el 19/10/2017
  12. Referencia del lenguaje Python, 2. Análisis léxico, 2.4.2. Concatenación de literales de cadena : "Se permiten múltiples literales de cadena adyacentes (delimitados por espacios en blanco), que posiblemente utilicen diferentes convenciones de comillas, y su significado es el mismo que el de su concatenación."
  13. 1 2 3 Python-ideas, "¿ Se considera perjudicial la concatenación implícita de literales de cadena? ", Guido van Rossum, 10 de mayo de 2013
  14. Referencia del lenguaje Python, 2. Análisis léxico, 2.4.2. Concatenación de literales de cadena : "Tenga en cuenta que esta característica se define a nivel sintáctico, pero se implementa en tiempo de compilación. El operador '+' debe usarse para concatenar expresiones de cadena en tiempo de ejecución."
  15. "Cadenas (Tutoriales de Java™ > Aprendiendo el lenguaje Java > Números y cadenas)" . Docs.oracle.com . 28 de febrero de 2012. Consultado el 22 de junio de 2016 .
  16. Fundamentos del lenguaje de programación ANSI C. Silicon Press. 1990. pág . 31. ISBN  0-929306-07-4.3.1.4 Literales de cadena : "Una cadena larga puede continuarse a lo largo de varias líneas utilizando la continuación de línea con barra invertida y salto de línea, pero esta práctica requiere que la continuación de la cadena comience en la primera posición de la siguiente línea. Para permitir una disposición más flexible y resolver algunos problemas de preprocesamiento (véase §3.8.3), el Comité introdujo la concatenación de literales de cadena. Dos literales de cadena consecutivos se unen (sin carácter nulo en el medio) para formar un literal de cadena combinado. Esta adición al lenguaje C permite al programador extender un literal de cadena más allá del final de una línea física sin tener que utilizar el mecanismo de barra invertida y salto de línea, evitando así la alteración del esquema de indentación del programa. No se introdujo un operador de concatenación explícito porque la concatenación es una construcción léxica y no una operación en tiempo de ejecución."
  17. Fundamentos del lenguaje de programación ANSI C. Silicon Press. 1990. pág. 6566. ISBN  0-929306-07-4.3.8.3.2 El operador # : "El operador # se ha introducido para la conversión a cadena. Solo puede utilizarse en una expansión #define. Provoca que el nombre formal del parámetro que le sigue se sustituya por un literal de cadena formado al convertir a cadena la secuencia real de tokens del argumento. En combinación con la concatenación de literales de cadena (véase §3.1.4), el uso de este operador permite la construcción de cadenas con la misma eficacia que mediante la sustitución de identificadores dentro de una cadena. Un ejemplo del estándar ilustra esta característica."
  18. Revista de Usuarios de C/C++, Volumen 19, pág. 50
  19. "python - ¿Por qué permitir la concatenación de literales de cadena?" . Stack Overflow . Consultado el 22/06/2016 .
  20. "LINE__ a cadena (stringify) usando directivas de preprocesador" . Decompile.com . 12 de octubre de 2006. Consultado el 22 de junio de 2016 .
  21. The Python Language Reference, 2. Análisis léxico, 2.4.2. Concatenación de literales de cadena : "Esta característica se puede utilizar para reducir el número de barras invertidas necesarias, para dividir cadenas largas convenientemente en líneas largas, o incluso para agregar comentarios a partes de cadenas, por ejemplo:
  22. Sistema de seguimiento de incidencias de DLang – Incidencia 3827 - Advertir sobre la concatenación implícita de literales de cadena adyacentes y, posteriormente, desaconsejarla
  23. Borrador del estándar C++11 , "Borrador de trabajo, estándar para el lenguaje de programación C++" (PDF) ., 2.14.5 Literales de cadena [lex.string], nota 13, págs. 28-29: "Cualquier otra concatenación se admite condicionalmente con un comportamiento definido por la implementación."
  24. "STR10-C. No concatenar literales de cadena de diferente tipo - Codificación segura - Estándares de codificación segura de CERT" . Archivado del original el 14 de julio de 2014. Recuperado el 3 de julio de 2014 .
  25. "2. Análisis léxico — Documentación de Python 2.7.12rc1" . python.org . Consultado el 22 de junio de 2016 .
  26. "perlop - perldoc.perl.org" . perl.org . Consultado el 22 de junio de 2016 .
  27. "2. Análisis léxico" . The Python Language Reference . Python Software Foundation. 2.4.1. Literales de cadena y bytes. Tanto los literales de cadena como los de bytes pueden ir precedidos opcionalmente de una letra o ; tales construcciones se denominan literales de cadena sin procesar y literales de bytes sin procesar respectivamente y tratan las barras invertidas como caracteres literales.'r''R'El término "cadena sin procesar" se utiliza en otras secciones de esta fuente.
  28. "2. Análisis léxico" . The Python Language Reference . Python Software Foundation. 2.4.1.1. Secuencias de escape.Las secuencias de escape en literales de cadena y bytes sin 'r'prefijo 'R'se interpretan según reglas similares a las utilizadas por el estándar C. Las secuencias de escape se decodifican en "cadenas ordinarias" como se puede indicar en la sección 2.4.3. f-cadenas.
  29. "2. Análisis léxico" . The Python Language Reference . Python Software Foundation. 2.4.3. f-strings. Una cadena literal formateada o f-string es una cadena literal que tiene como prefijo o .'f''F'
  30. "2. Análisis léxico" . The Python Language Reference . Python Software Foundation. 2.4.3. f-strings.Las secuencias de escape en las f-cadenas se decodifican como en las cadenas literales ordinarias, excepto cuando una f-cadena literal también está marcada como una cadena sin formato. Este último tipo de f-cadena se denomina "cadena formateada sin formato"; para más detalles, consulte la sección 2.4.1, Literales de cadena y bytes. Además, tenga en cuenta que, antes de Python 3.12, no se permitía el escape de barras invertidas dentro de un campo de reemplazo de f-cadena.
  31. V. Smith, Eric (1 de agosto de 2015). "PEP 498 – Interpolación de cadenas literales" . Propuestas de mejora de Python . Python Software Foundation. Resumen.El PEP 498 propone un nuevo mecanismo de formato de cadenas llamado interpolación literal de cadenas, y se refiere a las cadenas utilizadas en ese mecanismo como "cadenas f".
  • Literales en programación