Parcours
/
Julia
Julia
/
Exercices
/
Niveaux de logs
Niveaux de logs

Niveaux de logs

Exercice d'apprentissage

Introduction

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 :

  • Toutes les strings en Julia sont en Unicode.
  • Les strings qui se trouvent aussi être de l'ASCII (les lettres anglaises A à Z en majuscules et minuscules, les chiffres et quelques caractères de ponctuation) sont faciles à manipuler.
  • La plupart des autres systèmes d'écriture dans le monde sont possibles à manipuler, mais demandent plus d'attention.

Littéraux de chaînes de caractères

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"

Échappement de caractères

Comme la plupart des langages depuis C, Julia utilise une barre oblique inversée \ pour l'échappement :

  1. Pour saisir des caractères non imprimables, comme le saut de ligne \n dans l'exemple précédent.
  2. Pour protéger des caractères qui auraient autrement une signification spéciale, comme \$ (voir ci-dessous).

Indexation

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.

Construction de chaînes de caractères

Concaténation

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.

Répétition

Simple :

julia> repeat("Abc", 5)
"AbcAbcAbcAbcAbc"

Interpolation

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"

Fonctions de chaînes de caractères

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.

Longueur

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

Découpage

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.

Rechercher et remplacer

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.

Espaces blancs

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"

Changer la casse

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 "

Instructions

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 :

  • INFO
  • WARNING
  • ERROR

Tu as trois tâches ; chacune d'elles prend une ligne de log et te demande d'en faire quelque chose.

1. Récupère le message d'une ligne de log

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"

2. Récupère le niveau de log d'une ligne de log

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"

3. Reformate une ligne de log

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.

Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Julia Exercism

Prêt à commencer Niveaux de logs ?

Inscris-toi sur Exercism pour apprendre et maîtriser Julia avec 35 concepts128 exercices, et un vrai mentorat humain, le tout gratuitement.