Uma String em Julia é uma sequência ordenada de caracteres. Como o manual aponta: "É claro que o verdadeiro problema surge quando alguém pergunta o que é um caractere."
Muito dessa complexidade será abordada em mais detalhes no Conceito Chars, mas, resumidamente:
Em geral, as strings são delimitadas por aspas duplas " ".
As aspas simples ' ' são usadas apenas para Chars.
Também é possível usar aspas duplas triplas """ """, o que permite usar " dentro da string sem escapá-lo.
Mais importante ainda: a indentação extra indesejada é removida das strings de várias linhas.
julia> """
Multiline
"""
"Multiline\nString\n"
Como a maioria das linguagens a partir do C, Julia usa uma barra invertida \ para escapar:
\n do exemplo anterior.\$ (veja abaixo).Em princípio, strings podem ser indexadas exatamente como vetores:
julia> s[1], s[5]
('J', 'a')
Isso claramente funciona para uma string ASCII como "Julia", mas ignora a maioria das línguas do mundo.
Considere um dos caracteres de Beowulf, escrito em inglês antigo há cerca de 15 séculos.
"Hrōðgār" claramente tem 7 caracteres, mas nem todos são ASCII.
julia> king = "Hrōðgār"
"Hrōðgār"
julia> length(king)
7
julia> isascii(king)
false
# collect() converts to a Char vector:
julia> collect(king)
7-element Vector{Char}:
'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)
'r': ASCII/Unicode U+0072 (category Ll: Letter, lowercase)
'ō': Unicode U+014D (category Ll: Letter, lowercase)
'ð': Unicode U+00F0 (category Ll: Letter, lowercase)
'g': ASCII/Unicode U+0067 (category Ll: Letter, lowercase)
'ā': Unicode U+0101 (category Ll: Letter, lowercase)
'r': ASCII/Unicode U+0072 (category Ll: Letter, lowercase)
Indexar uma string como essa começa bem, mas em algum momento quebra:
julia> king[3]
'ō': Unicode U+014D (category Ll: Letter, lowercase)
julia> king[4]
ERROR: StringIndexError: invalid index [4], valid nearby indices [3]=>'ō', [5]=>'ð'
O problema é que indexar assim conta bytes, que, para strings não ASCII, não têm uma relação de 1:1 com os caracteres.
Um caractere Unicode/UTF-8 pode precisar de até 4 bytes para ser representado, e o Conceito Chars vai explorar isso mais a fundo.
Muitas linguagens usam + como operador de concatenação de strings, mas Julia não.
Pelo menos a mensagem de erro é útil.
julia> "s1 " + "s2"
ERROR: MethodError: no method matching +(::String, ::String)
The function `+` exists, but no method is defined for this combination of argument types.
String concatenation is performed with *
julia> "s1 " * "s2"
"s1 s2"
A função string() concatena um número arbitrário de strings.
julia> string("lots ", "of ", "bits")
"lots of bits"
A função join() faz o mesmo e também aceita um vetor de strings, concatenando-as com um separador especificado (por padrão, "").
julia> join(["lots", "of", "bits"], "_")
"lots_of_bits"
Observe que as strings são imutáveis, e a concatenação envolve cópia. Assim, concatenações repetidas dentro de um laço são ineficientes, e é melhor reunir os fragmentos em um vetor e juntá-los todos no final.
Simples:
julia> repeat("Abc", 5)
"AbcAbcAbcAbcAbc"
Muitas linguagens têm uma forma de inserir valores calculados em strings, embora haja uma discordância extraordinária sobre a melhor sintaxe a usar.
Em Julia, os valores interpolados são precedidos por $.
julia> myvar = 42
42
julia> "myvar evaluates to $myvar"
"myvar evaluates to 42"
julia> r = 5.3
5.3
julia> "A circle of radius $r has area $(π * r^2)"
"A circle of radius 5.3 has area 88.24733763933729"
Os parênteses são obrigatórios quando omiti-los deixaria o código ambíguo, mas são opcionais para um único identificador seguido de espaço em branco.
Para incluir um $ na string, escape-o como \$.
Observe a limitação de que a interpolação atualmente não permite formatação, como o número de casas decimais a exibir.
@sprintf()Para um controle mais refinado sobre a montagem de strings, Julia copia a função sprintf do C (e de várias linguagens posteriores: a Wikipédia lista cerca de 30).
Em Julia, isso é implementado como uma macro dentro do módulo Printf, daí o prefixo @.
julia> using Printf
julia> r = 5.3
5.3
julia> @sprintf("A circle of radius %.1f has area %.2f", r, π * r^2)
"A circle of radius 5.3 has area 88.25"
Por simplicidade, esta seção vai se concentrar nas funções que retornam uma nova string e deixam a entrada inalterada.
Muitas têm uma equivalente, com o sufixo ! no nome, que modifica a entrada no lugar.
Qual é o comprimento de uma string? Às vezes, depende de como você conta.
O caso simples são as strings ASCII, em que cada caractere ocupa 1 byte.
julia> string_asc = "Julia"
"Julia"
julia> length(string_asc)
5
julia> sizeof(string_asc)
5
A função length() retorna o número de caracteres, e a função sizeof(), o número de bytes.
Essa distinção se torna importante com outros conjuntos de caracteres:
julia> king = "Hrōðgār"
"Hrōðgār"
julia> length(king)
7
julia> sizeof(king)
10
Uma operação comum em programação é pegar uma string longa e dividi-la em pedaços, com base em uma string separadora de um ou mais caracteres.
De modo mais geral, usamos a função split().
O separador, por padrão, é (qualquer) espaço em branco, mas outros podem ser especificados.
julia> split("my little string")
3-element Vector{SubString{String}}:
"my"
"little"
"string"
julia> split("My_snake_case_string", "_")
4-element Vector{SubString{String}}:
"My"
"snake"
"case"
"string"
Esses exemplos dividem uma string em strings menores. Dividir uma string em caracteres é uma operação diferente.
Uma string contém uma substring especificada?
Curiosamente, há duas funções para testar isso: occursin() e contains() diferem apenas na ordem de seus argumentos.
julia> needle = "Julia"
"Julia"
julia> haystack = "Python, Julia and R"
"Python, Julia and R"
julia> occursin(needle, haystack)
true
julia> contains(haystack, needle)
true
Para ser mais específico quanto à posição:
julia> startswith(haystack, "Python")
true
julia> endswith(haystack, "Python")
false
Para obter os índices início:fim de uma substring, temos várias funções:
findfirst()findlast()findprev()findnext()julia> findfirst(needle, haystack)
9:13
Para substituir substrings, liste as mudanças usando a sintaxe x => y.
julia> replace("abc", "a"=>"b", "b"=>"c", "c"=>"a")
"bca"
Desde o Julia 1.7, a função replace pode receber um número arbitrário de mudanças, com a garantia de que nenhum caractere será alterado mais de uma vez durante a substituição.
A sintaxe x => y é chamada de pair, um tipo importante em Julia, abordado em mais detalhes no Conceito Dicts and Pairs.
Muitas vezes precisamos remover espaços em branco do início e/ou do fim de uma string.
As funções para isso são lstrip() (esquerda), rstrip() (direita) e strip() (ambos).
julia> strip("\n\t useful_bit\n\n")
"useful_bit"
Essas funções têm nomes bastante autoexplicativos:
julia> s = repeat("aBcD ", 5)
"aBcD aBcD aBcD aBcD aBcD "
julia> uppercase(s)
"ABCD ABCD ABCD ABCD ABCD "
julia> lowercase(s)
"abcd abcd abcd abcd abcd "
julia> titlecase(s) # Initial letter of each word uppercase
"Abcd Abcd Abcd Abcd Abcd "
Neste exercício você vai processar linhas de log.
Cada linha de log é uma string formatada assim: "[<LEVEL>]: <MESSAGE>".
Existem três níveis de log diferentes:
INFOWARNINGERRORVocê tem três tarefas, e cada uma delas recebe uma linha de log e pede que você faça algo com ela.
Implemente a função message para retornar a mensagem de uma linha de log:
julia> message("[ERROR]: Invalid operation")
"Invalid operation"
Qualquer espaço em branco no início ou no fim deve ser removido:
julia> message("[WARNING]: Disk almost full\r\n")
"Disk almost full"
Implemente a função log_level para retornar o nível de log de uma linha de log, que deve ser retornado em minúsculas:
julia> log_level("[ERROR]: Invalid operation")
"error"
Implemente a função reformat, que reformata a linha de log colocando a mensagem primeiro e o nível de log depois dela, entre parênteses:
julia> reformat("[INFO]: Operation completed")
"Operation completed (info)"
Observação: Todas as strings deste exercício estão em inglês e limitadas ao conjunto de caracteres ASCII. Os próximos Conceitos darão a chance de trabalhar com caracteres Unicode.
Crie sua conta no Exercism para aprender e dominar Julia com 35 conceitos128 exercícios e mentoria humana de verdade, tudo de graça.