Un String en Julia est une séquence ordonnée de caractères. Comme le manuel le souligne : « Bien sûr, le vrai problème surgit quand on se demande ce qu'est un caractère. »
Une grande partie de cette complexité sera traitée plus en détail dans le concept Chars, mais en bref :
En général, les strings sont encadrées par des guillemets doubles " ".
Les guillemets simples ' ' ne sont utilisés que pour les Chars.
Il est aussi possible d'utiliser des triples guillemets doubles """ """, ce qui permet d'utiliser " à l'intérieur de la chaîne sans échappement.
Plus important encore, l'indentation supplémentaire indésirable est supprimée des chaînes multilignes.
julia> """
Multiline
"""
"Multiline\nString\n"
Comme la plupart des langages depuis C, Julia utilise une barre oblique inversée \ pour l'échappement :
\n dans l'exemple précédent.\$ (voir ci-dessous).En principe, les strings peuvent être indexées exactement comme des vecteurs :
julia> s[1], s[5]
('J', 'a')
Cela fonctionne clairement pour une string ASCII comme « Julia », mais cela ignore la plupart des langues du monde.
Considérons l'un des caractères de Beowulf, écrit en vieil anglais il y a environ 15 siècles.
« Hrōðgār » compte clairement 7 caractères, mais tous ne sont pas 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)
L'indexation dans une string comme celle-ci commence bien, mais à un moment donné, elle se casse :
julia> king[3]
'ō': Unicode U+014D (category Ll: Letter, lowercase)
julia> king[4]
ERROR: StringIndexError: invalid index [4], valid nearby indices [3]=>'ō', [5]=>'ð'
Le problème est que ce type d'indexation compte des octets, qui pour les strings non-ASCII n'ont pas de relation 1:1 avec les caractères.
Un caractère Unicode/UTF-8 peut nécessiter jusqu'à 4 octets pour être représenté, et le concept Chars explorera cela plus en détail.
De nombreux langages utilisent + comme opérateur de concaténation de chaînes, mais pas Julia.
Au moins, le message d'erreur est utile.
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"
La fonction string() concatène un nombre arbitraire de chaînes.
julia> string("lots ", "of ", "bits")
"lots of bits"
La fonction join() fait la même chose, et prend aussi un vecteur de chaînes et les concatène avec un séparateur donné (par défaut "").
julia> join(["lots", "of", "bits"], "_")
"lots_of_bits"
Note que les chaînes sont immuables, et que la concaténation implique une copie. Ainsi, des concaténations répétées dans une boucle sont inefficaces, et il vaut mieux collecter les fragments dans un vecteur et les assembler tous à la fin.
Simple :
julia> repeat("Abc", 5)
"AbcAbcAbcAbcAbc"
De nombreux langages ont un moyen d'insérer des valeurs calculées dans des chaînes, bien qu'il y ait un désaccord extraordinaire sur la meilleure syntaxe à utiliser.
En Julia, les valeurs interpolées sont précédées de $.
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"
Les parenthèses sont obligatoires quand les omettre serait ambigu, mais optionnelles pour un identifiant unique suivi d'un espace.
Pour inclure un $ dans la chaîne, échappe-le avec \$.
Note la limitation : l'interpolation ne permet actuellement pas de formatage, comme le nombre de décimales à afficher.
@sprintf()Pour un contrôle plus fin de l'assemblage des chaînes, Julia copie la fonction sprintf du C (et de plusieurs langages ultérieurs : Wikipédia en liste environ 30).
En Julia, ceci est implémenté comme une macro dans le module Printf, d'où le préfixe @.
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"
Par souci de simplicité, cette section se concentrera sur les fonctions qui renvoient une nouvelle chaîne et laissent l'entrée inchangée.
Beaucoup ont un équivalent, nommé avec un suffixe !, qui modifient l'entrée sur place.
Quelle est la longueur d'une chaîne ? Parfois, cela dépend de la façon dont on compte.
Le cas simple est celui des chaînes ASCII, où chaque caractère occupe 1 octet.
julia> string_asc = "Julia"
"Julia"
julia> length(string_asc)
5
julia> sizeof(string_asc)
5
La fonction length() renvoie le nombre de caractères, et la fonction sizeof() le nombre d'octets.
Cette distinction devient importante avec d'autres jeux de caractères :
julia> king = "Hrōðgār"
"Hrōðgār"
julia> length(king)
7
julia> sizeof(king)
10
Une opération courante en programmation consiste à prendre une longue chaîne et à la découper en morceaux, sur la base d'une chaîne de séparation d'un ou plusieurs caractères.
De manière générale, on utilise la fonction split().
Le séparateur est par défaut (n'importe quel) espace blanc, mais d'autres peuvent être spécifiés.
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"
Ces exemples découpent une chaîne en strings plus petites. Découper une chaîne en caractères est une opération différente.
Une chaîne contient-elle une sous-chaîne spécifiée ?
Curieusement, il y a deux fonctions pour tester cela : occursin() et contains() ne diffèrent que par l'ordre de leurs arguments.
julia> needle = "Julia"
"Julia"
julia> haystack = "Python, Julia and R"
"Python, Julia and R"
julia> occursin(needle, haystack)
true
julia> contains(haystack, needle)
true
Pour être plus précis sur la position :
julia> startswith(haystack, "Python")
true
julia> endswith(haystack, "Python")
false
Pour obtenir les indices début:fin d'une sous-chaîne, nous avons plusieurs fonctions :
findfirst()findlast()findprev()findnext()julia> findfirst(needle, haystack)
9:13
Pour remplacer des sous-chaînes, listez les changements en utilisant la syntaxe x => y.
julia> replace("abc", "a"=>"b", "b"=>"c", "c"=>"a")
"bca"
Depuis Julia 1.7, la fonction replace peut prendre un nombre arbitraire de changements, avec la garantie qu'aucun caractère ne sera modifié plus d'une fois pendant le remplacement.
La syntaxe x => y est appelée une pair, un type important en Julia qui est couvert plus en détail dans le concept Dicts and Pairs.
On a souvent besoin de supprimer les espaces blancs de début et/ou de fin d'une chaîne.
Les fonctions pour cela sont lstrip() (gauche), rstrip() (droite), strip() (les deux).
julia> strip("\n\t useful_bit\n\n")
"useful_bit"
Ces fonctions ont des noms assez explicites :
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 "
Dans cet exercice, on va traiter des lignes de log.
Chaque ligne de log est une string au format suivant : "[<LEVEL>]: <MESSAGE>".
Il existe trois niveaux de log différents :
INFOWARNINGERRORTu as trois tâches ; chacune d'elles prend une ligne de log et te demande d'en faire quelque chose.
Implémente la fonction message pour qu'elle renvoie le message d'une ligne de log :
julia> message("[ERROR]: Invalid operation")
"Invalid operation"
Les espaces en début et en fin de ligne doivent être supprimés :
julia> message("[WARNING]: Disk almost full\r\n")
"Disk almost full"
Implémente la fonction log_level pour qu'elle renvoie, en minuscules, le niveau de log d'une ligne de log :
julia> log_level("[ERROR]: Invalid operation")
"error"
Implémente la fonction reformat qui reformate la ligne de log en plaçant le message en premier, suivi du niveau de log entre parenthèses :
julia> reformat("[INFO]: Operation completed")
"Operation completed (info)"
Note : Toutes les strings de cet exercice sont en anglais et se limitent au jeu de caractères ASCII. Les prochains concepts te donneront l'occasion de travailler avec des caractères Unicode.
Inscris-toi sur Exercism pour apprendre et maîtriser Julia avec 35 concepts128 exercices, et un vrai mentorat humain, le tout gratuitement.