Está en la página 1de 6

Strings 

Las cadenas(strings) son secuencias finitas de caracteres. Los caracteres pueden ser letras A, B,
C, etc., junto con números y signos de puntuación comunes. Estos caracteres están
estandarizados junto con una asignación a valores enteros entre 0 y 127 por el estándar ASCII.
Por supuesto, hay muchos otros caracteres que se utilizan en idiomas distintos del inglés,
incluidas variantes de los caracteres ASCII con acentos y otras modificaciones, escrituras
relacionadas como cirílico y griego, y escrituras completamente ajenas a ASCII e inglés,
incluyendo árabe, chino, Hebreo, hindi, japonés y coreano. The Unicode standard aborda las
complejidades de lo que es con exactitud un carácter y generalmente se acepta como el
estándar definitivo que aborda este problema. Julia hace que el manejo de texto ASCII simple
sea simple y eficiente, y el manejo de Unicode es lo más simple y eficiente posible, inclusive
pudiendo escribir en lenguaje C, funcionando como se espera. Si el código encuentra texto que
no es ASCII, fallará elegantemente con un mensaje de error claro, en lugar de introducir
silenciosamente resultados corruptos. Cuando esto sucede, modificar el código para manejar
datos que no son ASCII es sencillo.

String Basics
 
Los literales de cadena están delimitados por comillas dobles o comillas dobles triples, como
ejemplo tenemos:

julia> str = "Hola, mundo.\n"


"Hola, mundo.\n"

julia> """Contiene "comillas" caracteres"""


"Contiene \"comillas\" caracteres"

Si desea extraer un carácter de una cadena se puede de la siguiente manera:

julia> str[begin]
'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)

julia> str[1]
'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)

julia> str[5]
',': ASCII/Unicode U+002C (category Po: Punctuation, other)

julia> str[end]
'\n': ASCII/Unicode U+000A (category Cc: Other, control)

Puede realizar operaciones aritméticas y otras operaciones con “end”, como un valor normal:

julia> str[end-1]
'.': ASCII/Unicode U+002E (category Po: Punctuation, other)

julia> str[end÷2]
' ': ASCII/Unicode U+0020 (category Zs: Separator, space)

El uso de un índice menor que “begin” (1) o mayor que “end” genera un error:

julia> str[begin-1]
ERROR: BoundsError: attempt to access String
at index [0]
[...]

julia> str[end+1]
ERROR: BoundsError: attempt to access String
at index [15]
[...]

También puede extraer una “subcadena” mediante la indexación de rango:

julia> str[4:9]
"a, mun"

Observe que las expresiones str [k] y str [k: k] no dan el mismo resultado:

julia> str[5]
',': ASCII/Unicode U+002C (category Po: Punctuation, other)

julia> str[5:5]
","

El primero es un valor de un solo carácter de tipo “Char”, mientras que el último es un valor de
cadena que contiene solo un solo carácter. En Julia son cosas muy distintas.

La indexación de rango hace una copia de la parte seleccionada de la cadena original.


Alternativamente, es posible crear una vista en una cadena usando el tipo subcadena
(SubString, por ejemplo:

julia> str = "gran cadena"


"gran cadena"

julia> substr = SubString(str, 1, 4)


"gran"

Varias funciones estándar como “chop”, “chomp” o “strip” devuelven una subcadena.

Unicode and UTF-8 

Julia es totalmente compatible con cadenas y caracteres Unicode. Como se mencionó


anteriormente, en los literales de caracteres, los puntos de código Unicode se pueden
representar usando secuencias de escape Unicode \ u y \ U, así como todas las secuencias de
escape estándar de C. Estos también se pueden usar para escribir cadenas literales:

julia> x = "\u2200 x \u2203 y"


"∀ x ∃ y"

El hecho de que estos caracteres Unicode se muestren como escapes o como caracteres
especiales depende de la configuración regional de su terminal y su compatibilidad con
Unicode. Los literales de cadena se codifican mediante la codificación UTF-8. UTF-8 es una
codificación de ancho variable, lo que significa que no todos los caracteres están codificados
en el mismo número de bytes ("unidades de código"). En UTF-8, los caracteres ASCII, es decir,
aquellos con puntos de código inferiores a 0x80 (128), se codifican como en ASCII, utilizando
un solo byte, mientras que los puntos de código 0x80 y superiores se codifican utilizando
varios bytes, hasta cuatro por carácter.
Los índices de cadena en Julia se refieren a unidades de código (= bytes para UTF-8), los
bloques de construcción de ancho fijo que se utilizan para codificar caracteres arbitrarios
(puntos de código). Esto significa que no todos los índices de una cadena son necesariamente
índices válidos para un carácter. Si indexa en una cadena en un índice de bytes no válido, se
produce un error.

julia> x[1]
'∀': Unicode U+2200 (category Sm: Symbol, math)

julia> x[2]
ERROR: StringIndexError("∀ x ∃ y", 2)
[...]

julia> x[3]
ERROR: StringIndexError("∀ x ∃ y", 3)
Stacktrace:
[...]

julia> x[4]
' ': ASCII/Unicode U+0020 (category Zs: Separator, space)

En este caso, el carácter ∀ es un carácter de tres bytes, por lo que los índices 2 y 3 no son
válidos y el índice del siguiente carácter es 4; este siguiente índice válido puede calcularse
mediante nextind (x, 1), y el siguiente índice posterior mediante nextind (x, 4) y así
sucesivamente. Dado que end es siempre el último índice válido en una colección, end-1 hace
referencia a un índice de bytes no válido si el penúltimo carácter es multibyte.

julia> x[end-1]
' ': ASCII/Unicode U+0020 (category Zs: Separator, space)

julia> x[end-2]
ERROR: StringIndexError("∀ x ∃ y", 9)
Stacktrace:
[...]

julia> x[prevind(x, end, 2)]


'∃': Unicode U+2203 (category Sm: Symbol, math)

El primer caso funciona, porque el último carácter “y” y el espacio son caracteres de un byte,
mientras que end-2 indexa en el medio de la representación multibyte ∃. La forma correcta
para este caso es usar prevind (x, lastindex (x), 2) o, si está usando ese valor para indexar en x,
puede escribir x [prevind (x, end, 2)] y end se expande a último índice (x).

La extracción de una subcadena mediante la indexación de rango también espera índices de


bytes válidos o se produce un error:

julia> x[1:1]
"∀"

julia> x[1:2]
ERROR: StringIndexError("∀ x ∃ y", 2)
Stacktrace:
[...]
julia> x[1:4]
"∀ "

Debido a las codificaciones de longitud variable, la cantidad de caracteres en una cadena (dada
por longitud (x)) no siempre es la misma que la del último índice. Si itera a través de los índices
1 hasta los índices últimos y el índice en x, la secuencia de caracteres que se devuelve cuando
no se producen errores es la secuencia de caracteres que comprende la cadena x. Por lo tanto,
tenemos la identidad de que length (x) <= último índice (x), ya que cada carácter en una
cadena debe tener su propio índice. La siguiente es una forma ineficiente y detallada de iterar
a través de los caracteres de x:
julia> for i = firstindex(x):lastindex(x)
try
println(x[i])
catch
# ignore the index error
end
end

Las líneas en blanco en realidad tienen espacios. Afortunadamente, el lenguaje incómodo


anterior es innecesario para iterar a través de los caracteres en una cadena, ya que puede usar
la cadena como un objeto iterable, no se requiere manejo de excepciones:
julia> for c in x
println(c)
end

Si necesita obtener índices válidos para una cadena, puede usar las funciones nextind y
prevind para incrementar / disminuir al índice válido siguiente / anterior, como se mencionó
anteriormente. También puede usar la función eachindex para iterar sobre los índices de
caracteres válidos:
julia> collect(eachindex(x))
7-element Array{Int64,1}:
1
4
5
6
7
10
11
Para acceder a las unidades de código sin formato (bytes para UTF-8) de la codificación, puede
usar la función codeunit (x, i), donde el índice i corre consecutivamente de 1 a ncodeunits (x).
La función codeunits (x) devuelve un contenedor AbstractVector {UInt8} que le permite
acceder a estas unidades de código sin formato (bytes) como una matriz. Las cadenas de Julia
pueden contener secuencias de unidades de código UTF-8 no válidas. Esta convención permite
tratar cualquier secuencia de bytes como una cadena. En tales situaciones, una regla es que
cuando se analiza una secuencia de unidades de código de izquierda a derecha, los caracteres
están formados por la secuencia más larga de unidades de código de 8 bits que coincide con el
inicio de uno de los siguientes patrones de bits (cada x puede ser 0 o 1 ):

 0xxxxxxx;
 110xxxxx 10xxxxxx;
 1110xxxx 10xxxxxx 10xxxxxx;
 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx;
 10xxxxxx;
 11111xxx.
En particular, esto significa que las secuencias de unidades de código demasiado largas y altas
y sus prefijos se tratan como un solo carácter no válido en lugar de múltiples caracteres no
válidos. Esta regla se puede explicar mejor con un ejemplo:
julia> y = "\xc0\xa0\xe2\x88\xe2|"
"\xc0\xa0\xe2\x88\xe2|"

julia> foreach(display, y)
'\xc0\xa0': [overlong] ASCII/Unicode U+0020 (category Zs: Separator,
space)
'\xe2\x88': Malformed UTF-8 (category Ma: Malformed, bad data)
'\xe2': Malformed UTF-8 (category Ma: Malformed, bad data)
'|': ASCII/Unicode U+007C (category Sm: Symbol, math)

julia> isvalid.(collect(y))
4-element BitArray{1}:
0
0
0
1

julia> y2 = "\xf7\xbf\xbf\xbf"
"\U1fffff"

julia> foreach(display, y2)


'\U1fffff': Unicode U+1FFFFF (category In: Invalid, too high)

Podemos ver que las dos primeras unidades de código en la cadena y forman una codificación
demasiado larga de caracteres de espacio. No es válido, pero se acepta en una cadena como
un solo carácter. Las siguientes dos unidades de código forman un comienzo válido de una
secuencia UTF-8 de tres bytes. Sin embargo, la quinta unidad de código \ xe2 no es su
continuación válida. Por lo tanto, las unidades de código 3 y 4 también se interpretan como
caracteres mal formados en esta cadena. De manera similar, la unidad de código 5 forma un
carácter mal formado porque | no es una continuación válida. Finalmente, la cadena y2
contiene un punto de código demasiado alto.
Julia usa la codificación UTF-8 de forma predeterminada, y los paquetes pueden agregar
soporte para nuevas codificaciones. Por ejemplo, el paquete LegacyStrings.jl implementa los
tipos UTF16String y UTF32String.

También podría gustarte