Strings
Dizeler, karakterlerin sonlu dizileridir. Elbette, gerçek sorun, bir karakterin ne olduğunu sorduğunuzda gelir. İngilizce konuşanların aşina olduğu karakterler A
, B
, C
gibi harflerdir; bunlara sayılar ve yaygın noktalama işaretleri de dahildir. Bu karakterler, ASCII standardı tarafından 0 ile 127 arasındaki tam sayı değerlerine eşleştirilerek standartlaştırılmıştır. Elbette, aksanlar ve diğer modifikasyonlarla birlikte ASCII karakterlerinin varyantları, Kiril ve Yunan gibi ilgili yazı sistemleri ve Arapça, Çince, İbranice, Hintçe, Japonca ve Korece gibi ASCII ve İngilizce ile tamamen alakasız yazı sistemleri de dahil olmak üzere, diğer birçok karakter de vardır. Unicode standardı, bir karakterin tam olarak ne olduğunu ele alan karmaşıklıkları ele alır ve bu sorunu ele alan kesin standart olarak genel olarak kabul edilir. İhtiyaçlarınıza bağlı olarak, bu karmaşıklıkları tamamen göz ardı edebilir ve yalnızca ASCII karakterlerinin var olduğunu varsayabilirsiniz veya karşılaşabileceğiniz herhangi bir karakter veya kodlamayı işleyebilen kod yazabilirsiniz. Julia, düz ASCII metni ile çalışmayı basit ve verimli hale getirir ve Unicode ile çalışmak da mümkün olduğunca basit ve verimlidir. Özellikle, ASCII dizelerini işlemek için C tarzı dize kodu yazabilirsiniz ve bu kodlar, hem performans hem de anlam açısından beklendiği gibi çalışacaktır. Eğer böyle bir kod, ASCII dışı metinle karşılaşırsa, sessizce bozuk sonuçlar sunmak yerine, net bir hata mesajıyla nazikçe başarısız olacaktır. Bu olduğunda, ASCII dışı verileri işlemek için kodu değiştirmek oldukça basittir.
Julia'nın dizeleri hakkında birkaç dikkate değer yüksek düzey özellik bulunmaktadır:
- Julia'da dizeler (ve dize literalleri) için kullanılan yerleşik somut tür
String
'dır. Bu, Unicode karakterlerinin tam aralığını destekler ve UTF-8 kodlaması aracılığıyla yapılır. (Diğer Unicode kodlamalarına dönüştürmek içintranscode
fonksiyonu sağlanmıştır.) - Tüm dize türleri,
AbstractString
soyut türünün alt türleridir ve harici paketler ekAbstractString
alt türleri tanımlar (örneğin, diğer kodlamalar için). Bir dize argümanı bekleyen bir fonksiyon tanımlarsanız, herhangi bir dize türünü kabul etmek için türüAbstractString
olarak belirtmelisiniz. - C ve Java gibi, ancak çoğu dinamik dilden farklı olarak, Julia'nın
AbstractChar
olarak adlandırılan tek bir karakteri temsil etmek için birinci sınıf bir türü vardır. YerleşikChar
alt türü, herhangi bir Unicode karakterini temsil edebilen 32 bitlik bir ilkel türdür (ve UTF-8 kodlamasına dayanmaktadır). - Java'da olduğu gibi, dizeler değiştirilemez: bir
AbstractString
nesnesinin değeri değiştirilemez. Farklı bir dize değeri oluşturmak için, diğer dizelerin parçalarından yeni bir dize oluşturursunuz. - Kavram olarak, bir dize, indekslerden karakterlere kısmi bir fonksiyon olarak tanımlanır: bazı indeks değerleri için, hiçbir karakter değeri döndürülmez ve bunun yerine bir istisna fırlatılır. Bu, Unicode dizelerinin değişken genişlikteki kodlamaları için hem verimli hem de basit bir şekilde uygulanamayacak olan karakter indeksine göre değil, kodlanmış bir temsilin bayt indeksi ile dizelere verimli bir şekilde erişim sağlamaya olanak tanır.
Characters
Bir Char
değeri tek bir karakteri temsil eder: bu, özel bir literal temsili ve uygun aritmetik davranışları olan 32 bitlik bir ilkel türdür ve Unicode code point temsil eden bir sayısal değere dönüştürülebilir. (Julia paketleri, diğer text encodings için işlemleri optimize etmek üzere AbstractChar
'ın diğer alt türlerini tanımlayabilir.) İşte Char
değerlerinin nasıl girileceği ve gösterileceği (karakter literal'lerinin tek tırnak ile sınırlı olduğunu, çift tırnak ile değil, unutmayın):
julia> c = 'x'
'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)
julia> typeof(c)
Char
Bir Char
'ı kolayca tam sayı değerine, yani kod noktasına dönüştürebilirsiniz:
julia> c = Int('x')
120
julia> typeof(c)
Int64
32-bit mimarilerde, typeof(c)
Int32
olacaktır. Bir tam sayı değerini Char
'a geri dönüştürmek de aynı derecede kolaydır:
julia> Char(120)
'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)
Tüm tam sayı değerleri geçerli Unicode kod noktaları değildir, ancak performans için Char
dönüşümü her karakter değerinin geçerli olup olmadığını kontrol etmez. Her dönüştürülen değerin geçerli bir kod noktası olup olmadığını kontrol etmek istiyorsanız, isvalid
fonksiyonunu kullanın:
julia> Char(0x110000)
'\U110000': Unicode U+110000 (category In: Invalid, too high)
julia> isvalid(Char, 0x110000)
false
Bu yazı itibarıyla, geçerli Unicode kod noktaları U+0000
ile U+D7FF
ve U+E000
ile U+10FFFF
arasındadır. Bunların hepsi henüz anlaşılır anlamlar atanmamış olabilir veya uygulamalar tarafından mutlaka yorumlanabilir değildir, ancak bu değerlerin tamamı geçerli Unicode karakterleri olarak kabul edilmektedir.
Tek bir karakteri \u
ile ardından dört onaltılık basamak veya \U
ile ardından sekiz onaltılık basamak yazarak tek tırnak içinde girebilirsiniz (en uzun geçerli değer yalnızca altı basamak gerektirir):
julia> '\u0'
'\0': ASCII/Unicode U+0000 (category Cc: Other, control)
julia> '\u78'
'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)
julia> '\u2200'
'∀': Unicode U+2200 (category Sm: Symbol, math)
julia> '\U10ffff'
'\U10ffff': Unicode U+10FFFF (category Cn: Other, not assigned)
Julia sisteminizin yerel ayarlarını ve dil ayarlarını kullanarak hangi karakterlerin olduğu gibi yazılabileceğini ve hangilerinin genel, kaçış \u
veya \U
girdi biçimleriyle çıktılanması gerektiğini belirler. Bu Unicode kaçış biçimlerine ek olarak, C's traditional escaped input forms de kullanılabilir:
julia> Int('\0')
0
julia> Int('\t')
9
julia> Int('\n')
10
julia> Int('\e')
27
julia> Int('\x7f')
127
julia> Int('\177')
127
Char
değerleri ile karşılaştırmalar ve sınırlı miktarda aritmetik işlemler yapabilirsiniz:
julia> 'A' < 'a'
true
julia> 'A' <= 'a' <= 'Z'
false
julia> 'A' <= 'X' <= 'Z'
true
julia> 'x' - 'a'
23
julia> 'A' + 1
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
String Basics
Dize dizeleri çift tırnak veya üçlü çift tırnak ile sınırlıdır (tek tırnak ile değil):
julia> str = "Hello, world.\n"
"Hello, world.\n"
julia> """Contains "quote" characters"""
"Contains \"quote\" characters"
Uzun satırlar, yeni satırdan önce bir ters eğik çizgi (\
) ile bölünebilir:
julia> "This is a long \
line"
"This is a long line"
Bir dizeden bir karakter çıkarmak istiyorsanız, ona indeksle erişirsiniz:
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[6]
',': ASCII/Unicode U+002C (category Po: Punctuation, other)
julia> str[end]
'\n': ASCII/Unicode U+000A (category Cc: Other, control)
Birçok Julia nesnesi, dizeler de dahil olmak üzere, tam sayılarla indekslenebilir. İlk elemanın (bir dizenin ilk karakteri) indeksi firstindex(str)
ile döndürülür ve son elemanın (karakterin) indeksi lastindex(str)
ile döndürülür. begin
ve end
anahtar kelimeleri, belirtilen boyut boyunca ilk ve son indeksler için kısayol olarak bir indeksleme işlemi içinde kullanılabilir. Dize indekslemesi, Julia'daki çoğu indeksleme gibi 1 tabanlıdır: firstindex
her AbstractString
için her zaman 1
döndürür. Ancak aşağıda göreceğimiz gibi, lastindex(str)
genel olarak bir dize için length(str)
ile aynı değildir, çünkü bazı Unicode karakterleri birden fazla "kod birimi" kaplayabilir.
end
ile normal bir değer gibi aritmetik ve diğer işlemleri gerçekleştirebilirsiniz:
julia> str[end-1]
'.': ASCII/Unicode U+002E (category Po: Punctuation, other)
julia> str[end÷2]
' ': ASCII/Unicode U+0020 (category Zs: Separator, space)
begin
(1
) veya end
'den büyük bir indeks kullanmak bir hata oluşturur:
julia> str[begin-1]
ERROR: BoundsError: attempt to access 14-codeunit String at index [0]
[...]
julia> str[end+1]
ERROR: BoundsError: attempt to access 14-codeunit String at index [15]
[...]
Bir alt dizeyi aralık dizinleme kullanarak da çıkarabilirsiniz:
julia> str[4:9]
"lo, wo"
str[k]
ve str[k:k]
ifadelerinin aynı sonucu vermediğine dikkat edin:
julia> str[6]
',': ASCII/Unicode U+002C (category Po: Punctuation, other)
julia> str[6:6]
","
Öncelikle, ilki Char
türünde tek bir karakter değeridir, ikincisi ise yalnızca tek bir karakter içeren bir dize değeridir. Julia'da bunlar çok farklı şeylerdir.
Aralık dizinleme, orijinal dizenin seçilen kısmının bir kopyasını oluşturur. Alternatif olarak, SubString
türünü kullanarak bir dizenin içine bir görünüm oluşturmak mümkündür. Daha basit bir şekilde, bir kod bloğu üzerinde @views
makrosunu kullanmak, tüm dize dilimlerini alt dizelere dönüştürür. Örneğin:
julia> str = "long string"
"long string"
julia> substr = SubString(str, 1, 4)
"long"
julia> typeof(substr)
SubString{String}
julia> @views typeof(str[1:4]) # @views converts slices to SubStrings
SubString{String}
Birçok standart fonksiyon, chop
, chomp
veya strip
gibi, SubString
döndürmektedir.
Unicode and UTF-8
Julia tamamen Unicode karakterlerini ve dizelerini destekler. discussed above olarak, karakter literallerinde, Unicode kod noktaları Unicode \u
ve \U
kaçış dizileri kullanılarak temsil edilebilir, ayrıca tüm standart C kaçış dizileri de kullanılabilir. Bunlar aynı şekilde dize literalleri yazmak için de kullanılabilir:
julia> s = "\u2200 x \u2203 y"
"∀ x ∃ y"
Bu Unicode karakterlerinin kaçış olarak mı yoksa özel karakterler olarak mı görüntüleneceği, terminalinizin yerel ayarlarına ve Unicode desteğine bağlıdır. Dize literalleri UTF-8 kodlaması kullanılarak kodlanır. UTF-8, değişken genişlikte bir kodlama olup, tüm karakterlerin aynı sayıda bayt ("kod birimi") ile kodlanmadığı anlamına gelir. UTF-8'de, ASCII karakterleri — yani 0x80 (128) altındaki kod noktalarına sahip olanlar — ASCII'de olduğu gibi tek bir bayt kullanılarak kodlanırken, 0x80 ve üzerindeki kod noktaları birden fazla bayt kullanılarak kodlanır — karakter başına en fazla dört bayt.
Julia'da dize indeksleri, rastgele karakterleri (kod noktaları) kodlamak için kullanılan sabit genişlikteki yapı taşları olan kod birimlerine (= UTF-8 için baytlara) atıfta bulunur. Bu, bir String
içindeki her indeksin mutlaka bir karakter için geçerli bir indeks olmadığı anlamına gelir. Geçersiz bir bayt indeksinde bir dizeye indeksleme yaparsanız, bir hata fırlatılır:
julia> s[1]
'∀': Unicode U+2200 (category Sm: Symbol, math)
julia> s[2]
ERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'∀', [4]=>' '
Stacktrace:
[...]
julia> s[3]
ERROR: StringIndexError: invalid index [3], valid nearby indices [1]=>'∀', [4]=>' '
Stacktrace:
[...]
julia> s[4]
' ': ASCII/Unicode U+0020 (category Zs: Separator, space)
Bu durumda, ∀
karakteri üç baytlık bir karakterdir, bu nedenle 2 ve 3 indeksleri geçersizdir ve bir sonraki karakterin indeksi 4'tür; bu bir sonraki geçerli indeks nextind(s,1)
ile hesaplanabilir ve ondan sonraki indeks nextind(s,4)
ile hesaplanabilir ve bu şekilde devam eder.
end
her zaman bir koleksiyondaki son geçerli indeksi temsil ettiğinden, end-1
sondan bir önceki karakter çok baytlıysa geçersiz bir bayt indeksini referans alır.
julia> s[end-1]
' ': ASCII/Unicode U+0020 (category Zs: Separator, space)
julia> s[end-2]
ERROR: StringIndexError: invalid index [9], valid nearby indices [7]=>'∃', [10]=>' '
Stacktrace:
[...]
julia> s[prevind(s, end, 2)]
'∃': Unicode U+2203 (category Sm: Symbol, math)
İlk durum çalışır, çünkü son karakter y
ve boşluk birer baytlık karakterlerdir, oysa end-2
∃
çok baytlı temsilinin ortasına indekslenir. Bu durum için doğru yol prevind(s, lastindex(s), 2)
kullanmaktır veya bu değeri s
'ye indekslemek için s[prevind(s, end, 2)]
yazabilirsiniz ve end
lastindex(s)
'ye genişler.
Bir alt dizeyi aralık dizinleme kullanarak çıkarmak, geçerli bayt dizinleri bekler veya bir hata fırlatılır:
julia> s[1:1]
"∀"
julia> s[1:2]
ERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'∀', [4]=>' '
Stacktrace:
[...]
julia> s[1:4]
"∀ "
Değişken uzunlukta kodlamalar nedeniyle, bir dizedeki karakter sayısı (length(s)
) her zaman son indeksle aynı değildir. 1
ile lastindex(s)
arasındaki indekslerde yineleme yaparsanız ve s
'ye indeksleme yaparsanız, hata fırlatılmadığında döndürülen karakter dizisi, s
dizisini oluşturan karakterlerin dizisidir. Bu nedenle length(s) <= lastindex(s)
'dir, çünkü bir dizideki her karakterin kendi indeksi olmalıdır. Aşağıda, s
'nin karakterleri arasında yineleme yapmanın verimsiz ve ayrıntılı bir yolu verilmiştir:
julia> for i = firstindex(s):lastindex(s)
try
println(s[i])
catch
# ignore the index error
end
end
∀
x
∃
y
Boş satırlarda aslında boşluklar var. Neyse ki, yukarıdaki garip deyim, bir dizedeki karakterler arasında yinelemek için gereksizdir, çünkü dizeyi bir yineleyici nesne olarak kullanabilirsiniz, istisna işleme gerektirmez:
julia> for c in s
println(c)
end
∀
x
∃
y
Eğer bir dize için geçerli indeksler elde etmeniz gerekiyorsa, yukarıda bahsedilen nextind
ve prevind
fonksiyonlarını bir sonraki/geçerli indekse artırmak/azaltmak için kullanabilirsiniz. Ayrıca geçerli karakter indeksleri üzerinde yinelemek için eachindex
fonksiyonunu da kullanabilirsiniz:
julia> collect(eachindex(s))
7-element Vector{Int64}:
1
4
5
6
7
10
11
Ham hamur kod birimlerine (UTF-8 için baytlar) erişmek için codeunit(s,i)
fonksiyonunu kullanabilirsiniz; burada i
indeksi 1
'den ncodeunits(s)
'ya kadar ardışık olarak çalışır. codeunits(s)
fonksiyonu, bu ham kod birimlerine (baytlar) bir dizi olarak erişmenizi sağlayan bir AbstractVector{UInt8}
sarmalayıcı döndürür.
Julia'daki dizeler geçersiz UTF-8 kod birimi dizileri içerebilir. Bu kural, herhangi bir bayt dizisini String
olarak ele almayı sağlar. Bu tür durumlarda, soldan sağa bir kod birimi dizisini ayrıştırırken, karakterler aşağıdaki bit desenlerinden birinin başlangıcına uyan en uzun 8 bitlik kod birimi dizisi ile oluşturulur (her x
0
veya 1
olabilir):
0xxxxxxx
;110xxxxx
10xxxxxx
;1110xxxx
10xxxxxx
10xxxxxx
;11110xxx
10xxxxxx
10xxxxxx
10xxxxxx
;10xxxxxx
;11111xxx
.
Özellikle bu, aşırı uzun ve çok yüksek kod birimi dizilerinin ve bunların ön eklerinin tek bir geçersiz karakter olarak, birden fazla geçersiz karakter olarak değil, ele alındığı anlamına gelir. Bu kural en iyi bir örnekle açıklanabilir:
julia> s = "\xc0\xa0\xe2\x88\xe2|"
"\xc0\xa0\xe2\x88\xe2|"
julia> foreach(display, s)
'\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(s))
4-element BitArray{1}:
0
0
0
1
julia> s2 = "\xf7\xbf\xbf\xbf"
"\U1fffff"
julia> foreach(display, s2)
'\U1fffff': Unicode U+1FFFFF (category In: Invalid, too high)
İlk iki kod biriminin s
dizesinde boşluk karakterinin aşırı uzun bir kodlamasını oluşturduğunu görebiliriz. Geçersizdir, ancak bir dize içinde tek bir karakter olarak kabul edilir. Sonraki iki kod birimi, üç baytlık bir UTF-8 dizisinin geçerli başlangıcını oluşturur. Ancak, beşinci kod birimi \xe2
onun geçerli devamı değildir. Bu nedenle, kod birimleri 3 ve 4 de bu dizede bozuk karakterler olarak yorumlanır. Benzer şekilde, kod birimi 5, |
onun için geçerli bir devam olmadığı için bozuk bir karakter oluşturur. Son olarak, s2
dizesi bir kod noktasının çok yüksek olduğunu içerir.
Julia varsayılan olarak UTF-8 kodlamasını kullanır ve yeni kodlamalar için destek paketler aracılığıyla eklenebilir. Örneğin, LegacyStrings.jl paketi UTF16String
ve UTF32String
türlerini uygular. Diğer kodlamalar ve bunlar için destek sağlama yöntemleri ile ilgili ek tartışmalar, bu belgenin kapsamının ötesindedir. UTF-8 kodlama sorunları hakkında daha fazla tartışma için, aşağıdaki byte array literals bölümüne bakın. transcode
fonksiyonu, çeşitli UTF-xx kodlamaları arasında veri dönüştürmek için sağlanmıştır, esasen dış veriler ve kütüphanelerle çalışmak için.
Concatenation
En yaygın ve faydalı dize işlemlerinden biri birleştirmedir:
julia> greet = "Hello"
"Hello"
julia> whom = "world"
"world"
julia> string(greet, ", ", whom, ".\n")
"Hello, world.\n"
Potansiyel tehlikeli durumların, geçersiz UTF-8 dizelerinin birleştirilmesi gibi, farkında olmak önemlidir. Ortaya çıkan dize, giriş dizelerinden farklı karakterler içerebilir ve karakter sayısı birleştirilen dizelerin karakter sayılarının toplamından daha az olabilir, örneğin:
julia> a, b = "\xe2\x88", "\x80"
("\xe2\x88", "\x80")
julia> c = string(a, b)
"∀"
julia> collect.([a, b, c])
3-element Vector{Vector{Char}}:
['\xe2\x88']
['\x80']
['∀']
julia> length.([a, b, c])
3-element Vector{Int64}:
1
1
1
Bu durum yalnızca geçersiz UTF-8 dizeleri için meydana gelebilir. Geçerli UTF-8 dizeleri için birleştirme, dizelerdeki tüm karakterleri korur ve dize uzunluklarının toplamsallığını sağlar.
Julia ayrıca string birleştirme için *
sağlar:
julia> greet * ", " * whom * ".\n"
"Hello, world.\n"
*
kullanıcılar için şaşırtıcı bir seçim gibi görünse de, bu kullanım matematikte, özellikle soyut cebirde bir öncülüğe sahiptir.
Matematikte, +
genellikle komütatif bir işlemi belirtir; burada operandların sırası önemli değildir. Bunun bir örneği, aynı şekle sahip herhangi iki matris A
ve B
için A + B == B + A
olan matris toplamasıdır. Buna karşılık, *
genellikle komütatif olmayan bir işlemi belirtir; burada operandların sırası önemlidir. Bunun bir örneği, genel olarak A * B != B * A
olan matris çarpımıdır. Matris çarpımında olduğu gibi, dize birleştirme de komütatif değildir: greet * whom != whom * greet
. Bu nedenle, *
yaygın matematiksel kullanımla tutarlı olarak infiks dize birleştirme operatörü için daha doğal bir seçimdir.
More precisely, the set of all finite-length strings S together with the string concatenation operator *
forms a free monoid (S, *
). The identity element of this set is the empty string, ""
. Whenever a free monoid is not commutative, the operation is typically represented as \cdot
, *
, or a similar symbol, rather than +
, which as stated usually implies commutativity.
Interpolation
Dize ekleme kullanarak dizeler oluşturmak biraz zahmetli hale gelebilir. Ancak, string
gibi bu ayrıntılı çağrılara olan ihtiyacı azaltmak veya tekrar eden çarpımları önlemek için, Julia $
kullanarak dize literallerine interpolasyon yapmaya izin verir; Perl'deki gibi:
julia> greet = "Hello"; whom = "world";
julia> "$greet, $whom.\n"
"Hello, world.\n"
Bu, yukarıdaki dize birleştirmesine göre daha okunabilir ve kullanışlıdır - sistem bu görünüşte tek dize sabitini string(greet, ", ", whom, ".\n")
çağrısına dönüştürür.
En kısa tamamlanmış ifade $
işareti alındıktan sonra, değeri dizeye yerleştirilecek ifade olarak kabul edilir. Böylece, herhangi bir ifadeyi parantez kullanarak bir dizeye yerleştirebilirsiniz:
julia> "1 + 2 = $(1 + 2)"
"1 + 2 = 3"
Her iki birleştirme ve dize interpolasyonu, nesneleri dize biçimine dönüştürmek için string
çağrısını yapar. Ancak, string
aslında sadece print
'nın çıktısını döndürür, bu nedenle yeni türler 4d61726b646f776e2e436f64652822222c20227072696e742229_40726566
veya show
'ya yöntemler eklemelidir, string
yerine.
Çoğu AbstractString
olmayan nesne, literal ifadeler olarak nasıl girildiklerine yakın bir şekilde string'lere dönüştürülür:
julia> v = [1,2,3]
3-element Vector{Int64}:
1
2
3
julia> "v: $v"
"v: [1, 2, 3]"
string
AbstractString
ve AbstractChar
değerleri için kimliktir, bu nedenle bunlar kendileri olarak, tırnaksız ve kaçışsız bir şekilde dizelere yerleştirilir:
julia> c = 'x'
'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)
julia> "hi, $c"
"hi, x"
Bir dize literalinde $
karakterini dahil etmek için, onu bir ters eğik çizgi ile kaçırın:
julia> print("I have \$100 in my account.\n")
I have $100 in my account.
Triple-Quoted String Literals
Üçlü tırnaklar ("""..."""
) kullanılarak oluşturulan dizeler, daha uzun metin blokları oluşturmak için yararlı olabilecek bazı özel davranışlara sahiptir.
İlk olarak, üç tırnaklı dizeler de en az girintili satırın seviyesine göre girintisizleştirilir. Bu, girintili kod içinde dizeleri tanımlamak için yararlıdır. Örneğin:
julia> str = """
Hello,
world.
"""
" Hello,\n world.\n"
Bu durumda, kapanış """
öncesindeki son (boş) satır girinti seviyesini belirler.
Girintili seviye, tüm satırlardaki en uzun ortak başlangıç boşluk veya sekme dizisi olarak belirlenir; bu, açılış """
sonrasındaki satırları ve yalnızca boşluk veya sekme içeren satırları hariç tutar (kapanış """
içeren satır her zaman dahil edilir). Daha sonra, açılış """
sonrasındaki metin hariç tüm satırlardan, ortak başlangıç dizisi kaldırılır (bu diziyi ile başlayan yalnızca boşluk ve sekme içeren satırlar da dahil). Örneğin:
julia> """ This
is
a test"""
" This\nis\n a test"
Sonraki olarak, eğer açılış """
bir yeni satır ile takip ediliyorsa, yeni satır sonuçta oluşan string'den çıkarılır.
"""hello"""
eşittir
"""
hello"""
ama
"""
hello"""
bir satır sonu içerir.
Satır sonu boşluğu, girintiden sonra kaldırılır. Örneğin:
julia> """
Hello,
world."""
"Hello,\nworld."
Eğer yeni satır bir ters eğik çizgi ile kaldırılırsa, girinti de dikkate alınacaktır:
julia> """
Averylong\
word"""
"Averylongword"
Son boşluk değiştirilmeden bırakılır.
Üçlü tırnaklı dize literalleri, "
karakterlerini kaçırmadan içerebilir.
Not edin ki, tek veya üçlü tırnak içinde yer alan literal dizgelerde satır sonları, dizgede bir yeni satır (LF) karakteri \n
ile sonuçlanır, editörünüz satırları sonlandırmak için bir taşıyıcı dönüş \r
(CR) veya CRLF kombinasyonu kullanıyor olsa bile. Bir dizgede bir CR dahil etmek için, açık bir kaçış \r
kullanın; örneğin, literal dizgeyi "a CRLF line ending\r\n"
olarak girebilirsiniz.
Common Operations
Dize lexikografik olarak karşılaştırmak için standart karşılaştırma operatörlerini kullanabilirsiniz:
julia> "abracadabra" < "xylophone"
true
julia> "abracadabra" == "xylophone"
false
julia> "Hello, world." != "Goodbye, world."
true
julia> "1 + 2 = 3" == "1 + 2 = $(1 + 2)"
true
Belirli bir karakterin indeksini findfirst
ve findlast
fonksiyonlarını kullanarak arayabilirsiniz:
julia> findfirst('o', "xylophone")
4
julia> findlast('o', "xylophone")
7
julia> findfirst('z', "xylophone")
Belirli bir ofsetten bir karakter aramaya findnext
ve findprev
fonksiyonlarını kullanarak başlayabilirsiniz:
julia> findnext('o', "xylophone", 1)
4
julia> findnext('o', "xylophone", 5)
7
julia> findprev('o', "xylophone", 5)
4
julia> findnext('o', "xylophone", 8)
occursin
fonksiyonunu bir alt dizeyi bir dizede bulup bulmadığını kontrol etmek için kullanabilirsiniz:
julia> occursin("world", "Hello, world.")
true
julia> occursin("o", "Xylophon")
true
julia> occursin("a", "Xylophon")
false
julia> occursin('o', "Xylophon")
true
Son örnek, occursin
ifadesinin bir karakter literali arayabileceğini göstermektedir.
İki başka kullanışlı dize işlevi repeat
ve join
:
julia> repeat(".:Z:.", 10)
".:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:..:Z:."
julia> join(["apples", "bananas", "pineapples"], ", ", " and ")
"apples, bananas and pineapples"
Diğer bazı yararlı fonksiyonlar şunlardır:
firstindex(str)
dizenin içine indekslemek için kullanılabilecek en küçük (bayt) indeksini verir (her zaman dizeler için 1'dir, diğer konteynerler için bu geçerli olmayabilir).lastindex(str)
str
'ye indekslemek için kullanılabilecek en yüksek (bayt) indeks değerini verir.length(str)
str
içindeki karakter sayısı.length(str, i, j)
str
içindekii
ilej
arasındaki geçerli karakter indekslerinin sayısı.ncodeunits(str)
sayısı code units bir dizede.codeunit(str, i)
dizisistr
içindekii
indeksindeki kod birim değerini verir.thisind(str, i)
verilen bir dizgede rastgele bir indeks verildiğinde, indeksin işaret ettiği karakterin ilk indeksini bul.nextind(str, i, n=1)
i
indeksinden sonran
'inci karakterin başlangıcını bul.prevind(str, i, n=1)
n
'ncii
'den önceki karakterin başlangıcını bul.
Non-Standard String Literals
Bir dize oluşturmak veya dize anlamsalını kullanmak istediğiniz durumlar vardır, ancak standart dize yapısının davranışı tam olarak gerekli olan değildir. Bu tür durumlar için, Julia standart dışı dize literalleri sağlar. Standart dışı bir dize literali, normal çift tırnaklı dize literali gibi görünür, ancak hemen bir tanımlayıcı ile önceden gelir ve normal bir dize literali ile farklı davranabilir.
Regular expressions, byte array literals, ve version number literals, aşağıda açıklandığı gibi, standart dışı dize literallerinin bazı örnekleridir. Kullanıcılar ve paketler ayrıca yeni standart dışı dize literalleri tanımlayabilir. Daha fazla belge Metaprogramming bölümünde verilmiştir.
Regular Expressions
Bazen tam bir dize aramıyorsunuz, ancak belirli bir deseni arıyorsunuz. Örneğin, büyük bir metin dosyasından tek bir tarihi çıkarmaya çalıştığınızı varsayalım. O tarihin ne olduğunu bilmiyorsunuz (bu yüzden onu arıyorsunuz), ancak YYYY-AA-GG
gibi görüneceğini biliyorsunuz. Düzenli ifadeler, bu desenleri belirtmenize ve bunları aramanıza olanak tanır.
Julia, Perl uyumlu düzenli ifadelerin (regex) 2. sürümünü kullanır; bu, PCRE kütüphanesi tarafından sağlanmaktadır (daha fazla bilgi için PCRE2 syntax description'ye bakın). Düzenli ifadeler, iki şekilde dizelerle ilişkilidir: belirgin bağlantı, düzenli ifadelerin dizelerde düzenli desenleri bulmak için kullanılmasıdır; diğer bağlantı ise düzenli ifadelerin kendilerinin, dizeler olarak girilmesidir; bu dizeler, dizelerde desenleri verimli bir şekilde aramak için kullanılabilecek bir durum makinesine ayrıştırılır. Julia'da, düzenli ifadeler, r
ile başlayan çeşitli tanımlayıcılarla ön eklenmiş standart dışı dize literalleri kullanılarak girilir. Herhangi bir seçenek etkinleştirilmeden kullanılan en temel düzenli ifade literali sadece r"..."
kullanır:
julia> re = r"^\s*(?:#|$)"
r"^\s*(?:#|$)"
julia> typeof(re)
Regex
Bir regex'in bir dizeyle eşleşip eşleşmediğini kontrol etmek için occursin
kullanın:
julia> occursin(r"^\s*(?:#|$)", "not a comment")
false
julia> occursin(r"^\s*(?:#|$)", "# a comment")
true
Burada görüldüğü gibi, occursin
yalnızca verilen regex'in dizede bir eşleşme olup olmadığını belirten true veya false döndürür. Ancak genellikle, bir dize eşleştiğinde, sadece eşleşip eşleşmediğini değil, aynı zamanda nasıl eşleştiğini de bilmek istenir. Eşleşme hakkında bu bilgiyi yakalamak için match
fonksiyonunu kullanın:
julia> match(r"^\s*(?:#|$)", "not a comment")
julia> match(r"^\s*(?:#|$)", "# a comment")
RegexMatch("#")
Eğer düzenli ifade verilen dizeyle eşleşmiyorsa, match
nothing
döner - etkileşimli istemde hiçbir şey yazdırmayan özel bir değer. Yazdırmamanın dışında, tamamen normal bir değerdir ve programatik olarak test edebilirsiniz:
m = match(r"^\s*(?:#|$)", line)
if m === nothing
println("not a comment")
else
println("blank or comment")
end
Eğer bir düzenli ifade eşleşiyorsa, match
tarafından döndürülen değer bir RegexMatch
nesnesidir. Bu nesneler, ifadenin nasıl eşleştiğini kaydeder, eşleşen alt dizeyi ve varsa yakalanan alt dizeleri içerir. Bu örnek yalnızca eşleşen alt dizenin kısmını yakalar, ancak belki de yorum karakterinden sonraki herhangi bir boş olmayan metni yakalamak istiyoruz. Bunu şu şekilde yapabiliriz:
julia> m = match(r"^\s*(?:#\s*(.*?)\s*$)", "# a comment ")
RegexMatch("# a comment ", 1="a comment")
match
çağrıldığında, aramaya başlamak için bir indeks belirtme seçeneğiniz vardır. Örneğin:
julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",1)
RegexMatch("1")
julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",6)
RegexMatch("2")
julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",11)
RegexMatch("3")
RegexMatch
nesnesesinden aşağıdaki bilgileri çıkarabilirsiniz:
- eşleşen tüm alt dize:
m.match
- yakalanan alt dizeleri bir dizi dize olarak:
m.captures
- eşleşmenin başladığı ofset:
m.offset
- yakalanan alt dizelerin ofsetleri bir vektör olarak:
m.offsets
Bir eşleşme olmadığında, bir alt dize yerine m.captures
o pozisyonda nothing
içerir ve m.offsets
sıfır ofsetine sahiptir (Julia'daki indekslerin 1 tabanlı olduğunu hatırlayın, bu nedenle bir dizeye sıfır ofseti geçersizdir). İşte biraz yapay iki örnek:
julia> m = match(r"(a|b)(c)?(d)", "acd")
RegexMatch("acd", 1="a", 2="c", 3="d")
julia> m.match
"acd"
julia> m.captures
3-element Vector{Union{Nothing, SubString{String}}}:
"a"
"c"
"d"
julia> m.offset
1
julia> m.offsets
3-element Vector{Int64}:
1
2
3
julia> m = match(r"(a|b)(c)?(d)", "ad")
RegexMatch("ad", 1="a", 2=nothing, 3="d")
julia> m.match
"ad"
julia> m.captures
3-element Vector{Union{Nothing, SubString{String}}}:
"a"
nothing
"d"
julia> m.offset
1
julia> m.offsets
3-element Vector{Int64}:
1
0
2
Bir dizi olarak dönen yakalamaların olması, bunları yerel değişkenlere bağlamak için yapısal sözdizimini kullanmayı kolaylaştırır. Kolaylık olması açısından, RegexMatch
nesnesi, captures
alanına geçiş yapan yineleyici yöntemlerini uygular, böylece eşleşme nesnesini doğrudan yapısal hale getirebilirsiniz:
julia> first, second, third = m; first
"a"
Kapsamlar, RegexMatch
nesnesini yakalama grubunun numarası veya adıyla dizinleyerek de erişilebilir:
julia> m=match(r"(?<hour>\d+):(?<minute>\d+)","12:45")
RegexMatch("12:45", hour="12", minute="45")
julia> m[:minute]
"45"
julia> m[2]
"45"
Yakalamalar, replace
kullanırken bir yer değiştirme dizesinde referans alınabilir; \n
kullanarak n'inci yakalama grubuna atıfta bulunabilir ve yer değiştirme dizesini s
ile öne alabilirsiniz. Yakalama grubu 0, tüm eşleşme nesnesine atıfta bulunur. İsimli yakalama grupları, yer değiştirmede \g<grupadi>
ile referans alınabilir. Örneğin:
julia> replace("first second", r"(\w+) (?<agroup>\w+)" => s"\g<agroup> \1")
"second first"
Numaralı yakalama grupları, ayrıştırma için \g<n>
olarak da referans verilebilir, örneğin:
julia> replace("a", r"." => s"\g<0>1")
"a1"
Düzenli ifadelerin davranışını, kapanış çift tırnak işaretinden sonra i
, m
, s
ve x
bayraklarının bir kombinasyonu ile değiştirebilirsiniz. Bu bayraklar, Perl'deki anlamlarıyla aynı anlama sahiptir; bu, perlre manpage adresinden alınan bu alıntıda açıklandığı gibidir:
i Do case-insensitive pattern matching.
If locale matching rules are in effect, the case map is taken
from the current locale for code points less than 255, and
from Unicode rules for larger code points. However, matches
that would cross the Unicode rules/non-Unicode rules boundary
(ords 255/256) will not succeed.
m Treat string as multiple lines. That is, change "^" and "$"
from matching the start or end of the string to matching the
start or end of any line anywhere within the string.
s Treat string as single line. That is, change "." to match any
character whatsoever, even a newline, which normally it would
not match.
Used together, as r""ms, they let the "." match any character
whatsoever, while still allowing "^" and "$" to match,
respectively, just after and just before newlines within the
string.
x Tells the regular expression parser to ignore most whitespace
that is neither backslashed nor within a character class. You
can use this to break up your regular expression into
(slightly) more readable parts. The '#' character is also
treated as a metacharacter introducing a comment, just as in
ordinary code.
Örneğin, aşağıdaki regex'in tüm üç bayrağı açık:
julia> r"a+.*b+.*d$"ism
r"a+.*b+.*d$"ims
julia> match(r"a+.*b+.*d$"ism, "Goodbye,\nOh, angry,\nBad world\n")
RegexMatch("angry,\nBad world")
r"..."
literali, interpolasyon ve kaçış olmadan (yalnızca tırnak işareti "
hala kaçırılmak zorundadır) oluşturulur. İşte standart dize literallerinden farkı gösteren bir örnek:
julia> x = 10
10
julia> r"$x"
r"$x"
julia> "$x"
"10"
julia> r"\x"
r"\x"
julia> "\x"
ERROR: syntax: invalid escape sequence
Üçlü tırnaklı regex dizeleri, r"""..."""
biçiminde, desteklenmektedir (ve alıntı işaretleri veya yeni satırlar içeren düzenli ifadeler için kullanışlı olabilir).
Regex()
yapıcısı, geçerli bir regex dizesini programlı olarak oluşturmak için kullanılabilir. Bu, regex dizesini oluştururken dize değişkenlerinin ve diğer dize işlemlerinin içeriğini kullanmayı mümkün kılar. Yukarıdaki regex kodlarının herhangi biri Regex()
'in tek dize argümanı içinde kullanılabilir. İşte bazı örnekler:
julia> using Dates
julia> d = Date(1962,7,10)
1962-07-10
julia> regex_d = Regex("Day " * string(day(d)))
r"Day 10"
julia> match(regex_d, "It happened on Day 10")
RegexMatch("Day 10")
julia> name = "Jon"
"Jon"
julia> regex_name = Regex("[\"( ]\\Q$name\\E[\") ]") # interpolate value of name
r"[\"( ]\QJon\E[\") ]"
julia> match(regex_name, " Jon ")
RegexMatch(" Jon ")
julia> match(regex_name, "[Jon]") === nothing
true
\Q...\E
kaçış dizisinin kullanımına dikkat edin. \Q
ve \E
arasındaki tüm karakterler, literal karakterler olarak yorumlanır. Bu, aksi takdirde regex metakarakterleri olabilecek karakterleri eşleştirmek için kullanışlıdır. Ancak, bu özelliği dize interpolasyonu ile birlikte kullanırken dikkatli olunması gerekir, çünkü interpolasyon yapılan dize kendisi \E
dizisini içerebilir ve bu da literal eşleşmeyi beklenmedik bir şekilde sonlandırabilir. Kullanıcı girdileri, bir regex'e dahil edilmeden önce temizlenmelidir.
Byte Array Literals
Başka yararlı bir standart dışı dize literalı, byte-dizisi dize literalıdır: b"..."
. Bu form, yalnızca okunabilir literal byte dizilerini ifade etmek için dize notasyonunu kullanmanıza olanak tanır - yani UInt8
değerlerinin dizileri. Bu nesnelerin türü CodeUnits{UInt8, String}
'dir. Byte dizi literal kuralları şunlardır:
- ASCII karakterleri ve ASCII kaçışları tek bir bayt üretir.
\x
ve sekizli kaçış dizileri, kaçış değerine karşılık gelen baytı üretir.- Unicode kaçış dizileri, o kod noktasını UTF-8'de kodlayan bir bayt dizisi üretir.
Bu kurallar arasında bazı örtüşmeler vardır çünkü \x
ve 0x80'den (128) daha küçük sekizli kaçışların davranışı ilk iki kural tarafından kapsanmaktadır, ancak burada bu kurallar hemfikir. Birlikte, bu kuralların hepsi, ASCII karakterlerini, rastgele bayt değerlerini ve UTF-8 dizilerini kullanarak bayt dizileri üretmeyi kolaylaştırır. İşte her üçünü de kullanan bir örnek:
julia> b"DATA\xff\u2200"
8-element Base.CodeUnits{UInt8, String}:
0x44
0x41
0x54
0x41
0xff
0xe2
0x88
0x80
ASCII dizisi "DATA" 68, 65, 84, 65 baytlarına karşılık gelir. \xff
tek bir bayt olan 255'i üretir. Unicode kaçışı \u2200
, UTF-8'de üç bayt olan 226, 136, 128 olarak kodlanır. Sonuçta elde edilen bayt dizisinin geçerli bir UTF-8 dizesine karşılık gelmediğine dikkat edin:
julia> isvalid("DATA\xff\u2200")
false
CodeUnits{UInt8, String}
türü, UInt8
'in yalnızca okunabilir bir dizisi gibi davranır ve standart bir vektöre ihtiyacınız varsa, bunu Vector{UInt8}
kullanarak dönüştürebilirsiniz:
julia> x = b"123"
3-element Base.CodeUnits{UInt8, String}:
0x31
0x32
0x33
julia> x[1]
0x31
julia> x[1] = 0x32
ERROR: CanonicalIndexError: setindex! not defined for Base.CodeUnits{UInt8, String}
[...]
julia> Vector{UInt8}(x)
3-element Vector{UInt8}:
0x31
0x32
0x33
Ayrıca \xff
ve \uff
arasındaki önemli farkı gözlemleyin: ilk kaçış dizisi byte 255'i kodlarken, ikincisi kod noktası 255'i temsil eder; bu, UTF-8'de iki byte olarak kodlanır:
julia> b"\xff"
1-element Base.CodeUnits{UInt8, String}:
0xff
julia> b"\uff"
2-element Base.CodeUnits{UInt8, String}:
0xc3
0xbf
Karakter literalleri aynı davranışı kullanır.
<\u80
'den daha düşük kod noktaları için, her kod noktasının UTF-8 kodlamasının, karşılık gelen \x
kaçışından üretilen tek bayt olduğu durumlar vardır, bu nedenle ayrım güvenle göz ardı edilebilir. Ancak \x80
ile \xff
arasındaki kaçışlar ile \u80
ile \uff
arasındaki kaçışlar arasında büyük bir fark vardır: ilk kaçışlar tümüyle tek baytları kodlarken, - çok özel devam baytları ile takip edilmediği sürece - geçerli UTF-8 verileri oluşturmazken, sonuncu kaçışlar tümüyle iki baytlı kodlamalarla Unicode kod noktalarını temsil eder.
Eğer bu her şey son derece kafa karıştırıcıysa, "The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets" okuyarak başlayabilirsiniz. Bu, Unicode ve UTF-8'e mükemmel bir giriş niteliğindedir ve konuyla ilgili bazı kafa karışıklıklarını gidermeye yardımcı olabilir.
Version Number Literals
Sürüm numaraları, v"..."
biçimindeki standart dışı dize literalleri ile kolayca ifade edilebilir. Sürüm numarası literalleri, semantic versioning spesifikasyonlarını takip eden VersionNumber
nesneleri oluşturur ve bu nedenle ana, alt ve yaman sayısal değerlerden oluşur, ardından ön sürüm ve yapı alfasayısal notasyonlar gelir. Örneğin, v"0.2.1-rc1+win64"
ana sürüm 0
, alt sürüm 2
, yaman sürüm 1
, ön sürüm rc1
ve yapı win64
olarak ayrılır. Bir sürüm literali girerken, ana sürüm numarası dışındaki her şey isteğe bağlıdır, bu nedenle örneğin v"0.2"
ifadesi v"0.2.0"
(boş ön sürüm/yapı notasyonları ile) ile eşdeğerdir, v"2"
ifadesi v"2.0.0"
ile eşdeğerdir ve bu şekilde devam eder.
VersionNumber
nesneleri, iki (veya daha fazla) versiyonu kolayca ve doğru bir şekilde karşılaştırmak için genellikle faydalıdır. Örneğin, sabit VERSION
, Julia sürüm numarasını bir VersionNumber
nesnesi olarak tutar ve bu nedenle bazı sürüm-spesifik davranışları basit ifadeler kullanarak tanımlamak mümkündür:
if v"0.2" <= VERSION < v"0.3-"
# do something specific to 0.2 release series
end
Not edin ki yukarıdaki örnekte standart dışı sürüm numarası v"0.3-"
kullanılmıştır, sonundaki -
ile: bu notasyon, standartın bir Julia uzantısıdır ve 0.3
sürümünden daha düşük bir sürümü belirtmek için kullanılır, tüm ön sürümleri de dahil. Bu nedenle yukarıdaki örnekte kod yalnızca kararlı 0.2
sürümleri ile çalışacak ve v"0.3.0-rc1"
gibi sürümleri hariç tutacaktır. Ayrıca kararsız (yani ön sürüm) 0.2
sürümlerine de izin vermek için, alt sınır kontrolü şu şekilde değiştirilmelidir: v"0.2-" <= VERSION
.
Başka bir standart dışı sürüm spesifikasyonu uzantısı, bir üst sınır ifade etmek için bir +
eklemeye izin verir; örneğin, VERSION > v"0.2-rc1+"
ifadesi, 0.2-rc1
'den ve onun herhangi bir derlemesinden daha yüksek olan herhangi bir sürümü ifade etmek için kullanılabilir: v"0.2-rc1+win64"
sürümü için false
döner ve v"0.2-rc2"
için true
döner.
Özellikle, üst sınırlar için her zaman sonundaki -
işaretinin kullanılmasının iyi bir uygulama olduğu, ancak bunların herhangi bir şeyin gerçek sürüm numarası olarak kullanılmaması gerektiği, çünkü bunların anlamsal sürümleme şemasında geçersiz olduğu iyi bir uygulamadır.
VERSION
sabitinin yanı sıra, VersionNumber
nesneleri Pkg
modülünde, paket sürümlerini ve bunların bağımlılıklarını belirtmek için yaygın olarak kullanılmaktadır.
Raw String Literals
Hamur string'leri, interpolasyon veya unescape etme olmadan, raw"..."
biçiminde standart dışı string literalleri ile ifade edilebilir. Hamur string literalleri, içeriklerini tam olarak girildiği gibi, interpolasyon veya unescape etme olmadan içeren sıradan String
nesneleri oluşturur. Bu, $
veya \
gibi özel karakterler kullanan diğer dillerdeki kod veya işaretleme içeren string'ler için faydalıdır.
İstisna, alıntı işaretlerinin hala kaçış karakteri ile gösterilmesi gerektiğidir; örneğin, raw"\""
ifadesi "\""
ile eşdeğerdir. Tüm dizeleri ifade edebilmek için, ters eğik çizgilerin de kaçış karakteri ile gösterilmesi gerekir, ancak yalnızca bir alıntı karakterinin hemen önünde göründüğünde:
julia> println(raw"\\ \\\"")
\\ \"
İlk iki ters eğik çizginin çıktıda olduğu gibi göründüğüne dikkat edin, çünkü bunlar bir alıntı karakterinden önce gelmiyor. Ancak, sonraki ters eğik çizgi, onu takip eden ters eğik çizgiyi kaçar ve son ters eğik çizgi bir alıntıyı kaçar, çünkü bu ters eğik çizgiler bir alıntıdan önce gelir.
Annotated Strings
AnnotatedStrings API'si deneysel olarak kabul edilmektedir ve Julia sürümleri arasında değişiklik göstermesi muhtemeldir.
Bazen bir dize ile ilgili bölgeleri tutmak için meta verileri saklamak faydalı olabilir. Bir AnnotatedString
, başka bir dizeyi sarar ve bunun bölgelerinin etiketli değerlerle (:label => value
) anotasyon yapılmasına olanak tanır. Tüm genel dize işlemleri, temel dizeye uygulanır. Ancak, mümkün olduğunda stil bilgileri korunur. Bu, bir 4d61726b646f776e2e436f64652822222c2022416e6e6f7461746564537472696e672229_4072656620426173652e416e6e6f7461746564537472696e67
üzerinde alt dizeler alabileceğiniz, bunları doldurabileceğiniz, diğer dizelerle birleştirebileceğiniz anlamına gelir ve meta veri anotasyonları "yolda gelir".
Bu dize türü, stil bilgilerini tutmak için :face
etiketli notasyonlar kullanan StyledStrings stdlib için temeldir.
AnnotatedString
ile birleştirirken, dize açıklamalarını korumak istiyorsanız annotatedstring
kullanmaya dikkat edin, string
yerine.
julia> str = Base.AnnotatedString("hello there",
[(1:5, :word, :greeting), (7:11, :label, 1)])
"hello there"
julia> length(str)
11
julia> lpad(str, 14)
" hello there"
julia> typeof(lpad(str, 7))
Base.AnnotatedString{String}
julia> str2 = Base.AnnotatedString(" julia", [(2:6, :face, :magenta)])
" julia"
julia> Base.annotatedstring(str, str2)
"hello there julia"
julia> str * str2 == Base.annotatedstring(str, str2) # *-concatenation still works
true
AnnotatedString
anotasyonları annotations
ve annotate!
fonksiyonları aracılığıyla erişilebilir ve değiştirilebilir.