Dizeden alt dizeleri ayıklama

Bu makalede, bir dizenin bölümlerini ayıklamaya yönelik bazı farklı teknikler yer alır.

String.Split yöntemi

String.Split , bir dizeyi, belirttiğiniz bir veya daha fazla sınırlayıcı karaktere göre bir alt dize grubuna ayırmanıza yardımcı olacak birkaç aşırı yükleme sağlar. Son sonuçtaki toplam alt dize sayısını sınırlamayı, alt dizelerdeki boşluk karakterlerini kırpmayı veya boş alt dizeleri hariç tutmayı seçebilirsiniz.

Aşağıdaki örneklerde String.Split()'nin üç farklı aşırı yüklemesi gösterilmektedir. İlk örnek, herhangi bir ayırıcı karakter belirtmeden Split(Char[]) aşırı yüklemesini çağırır. Sınırlayıcı karakter belirtmediğinizde, String.Split() dizeyi bölmek için boşluk karakterleri olan varsayılan sınırlayıcıları kullanır.

string s = "You win some. You lose some.";

string[] subs = s.Split();

foreach (string sub in subs)
{
    Console.WriteLine($"Substring: {sub}");
}

// This example produces the following output:
//
// Substring: You
// Substring: win
// Substring: some.
// Substring: You
// Substring: lose
// Substring: some.
Dim s As String = "You win some. You lose some."
Dim subs As String() = s.Split()

For Each substring As String In subs
    Console.WriteLine("Substring: {0}", substring)
Next

' This example produces the following output:
'
' Substring: You
' Substring: win
' Substring: some.
' Substring: You
' Substring: lose
' Substring: some.

Gördüğünüz gibi nokta karakterleri (.) iki alt dizeye eklenir. Nokta karakterlerini dışlamak istiyorsanız, nokta karakterini ek bir sınırlandırma karakteri olarak ekleyebilirsiniz. Sonraki örnekte bunun nasıl yapıldığını gösterilmektedir.

string s = "You win some. You lose some.";

string[] subs = s.Split(' ', '.');

foreach (string sub in subs)
{
    Console.WriteLine($"Substring: {sub}");
}

// This example produces the following output:
//
// Substring: You
// Substring: win
// Substring: some
// Substring:
// Substring: You
// Substring: lose
// Substring: some
// Substring:
Dim s As String = "You win some. You lose some."
Dim subs As String() = s.Split(" "c, "."c)

For Each substring As String In subs
    Console.WriteLine("Substring: {0}", substring)
Next

' This example produces the following output:
'
' Substring: You
' Substring: win
' Substring: some
' Substring:
' Substring: You
' Substring: lose
' Substring: some
' Substring:

Dönemler alt dizelerden silindi, ancak artık fazladan iki boş alt dize dahil edildi. Bu boş alt dize, sözcükle onu izleyen nokta arasındaki alt dizeyi temsil eder. Sonuçta elde edilen dizideki boş alt dizeleri çıkarmak için Split(Char[], StringSplitOptions) aşırı yüklemesini çağırabilir ve options parametresi için StringSplitOptions.RemoveEmptyEntries belirtebilirsiniz.

string s = "You win some. You lose some.";
char[] separators = new char[] { ' ', '.' };

string[] subs = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);

foreach (string sub in subs)
{
    Console.WriteLine($"Substring: {sub}");
}

// This example produces the following output:
//
// Substring: You
// Substring: win
// Substring: some
// Substring: You
// Substring: lose
// Substring: some
Dim s As String = "You win some. You lose some."
Dim separators As Char() = New Char() {" "c, "."c}
Dim subs As String() = s.Split(separators, StringSplitOptions.RemoveEmptyEntries)

For Each substring As String In subs
    Console.WriteLine("Substring: {0}", substring)
Next

' This example produces the following output:
'
' Substring: You
' Substring: win
' Substring: some
' Substring: You
' Substring: lose
' Substring: some

Normal ifadeler

Dizeniz sabit bir desene uygunsa, öğelerini ayıklamak ve işlemek için normal bir ifade kullanabilirsiniz. Örneğin, dizeler "sayıişlemcisayı" biçimindeyse, dizenin öğelerini ayıklamak ve işlemek için bir düzenli ifade kullanabilirsiniz. Bir örnek aşağıda verilmiştir:

String[] expressions = { "16 + 21", "31 * 3", "28 / 3",
                       "42 - 18", "12 * 7",
                       "2, 4, 6, 8" };
String pattern = @"(\d+)\s+([-+*/])\s+(\d+)";

foreach (string expression in expressions)
{
    foreach (System.Text.RegularExpressions.Match m in
    System.Text.RegularExpressions.Regex.Matches(expression, pattern))
    {
        int value1 = Int32.Parse(m.Groups[1].Value);
        int value2 = Int32.Parse(m.Groups[3].Value);
        switch (m.Groups[2].Value)
        {
            case "+":
                Console.WriteLine($"{m.Value} = {value1 + value2}");
                break;
            case "-":
                Console.WriteLine($"{m.Value} = {value1 - value2}");
                break;
            case "*":
                Console.WriteLine($"{m.Value} = {value1 * value2}");
                break;
            case "/":
                Console.WriteLine($"{m.Value} = {value1 / value2:N2}");
                break;
        }
    }
}

// The example displays the following output:
//       16 + 21 = 37
//       31 * 3 = 93
//       28 / 3 = 9.33
//       42 - 18 = 24
//       12 * 7 = 84
Dim expressions() As String = {"16 + 21", "31 * 3", "28 / 3",
                              "42 - 18", "12 * 7",
                              "2, 4, 6, 8"}

Dim pattern As String = "(\d+)\s+([-+*/])\s+(\d+)"
For Each expression In expressions
    For Each m As Match In Regex.Matches(expression, pattern)
        Dim value1 As Integer = Int32.Parse(m.Groups(1).Value)
        Dim value2 As Integer = Int32.Parse(m.Groups(3).Value)
        Select Case m.Groups(2).Value
            Case "+"
                Console.WriteLine("{0} = {1}", m.Value, value1 + value2)
            Case "-"
                Console.WriteLine("{0} = {1}", m.Value, value1 - value2)
            Case "*"
                Console.WriteLine("{0} = {1}", m.Value, value1 * value2)
            Case "/"
                Console.WriteLine("{0} = {1:N2}", m.Value, value1 / value2)
        End Select
    Next
Next

' The example displays the following output:
'       16 + 21 = 37
'       31 * 3 = 93
'       28 / 3 = 9.33
'       42 - 18 = 24
'       12 * 7 = 84

Normal ifade düzeni (\d+)\s+([-+*/])\s+(\d+) şöyle tanımlanır:

Desen Açıklama
(\d+) Bir veya daha fazla ondalık basamağı eşleştirin. Bu ilk yakalama grubudur.
\s+ Bir veya daha fazla boşluk karakteri eşleştirin.
([-+*/]) Aritmetik bir işleç işaretiyle (+, -, *, veya /) eşleştir. Bu ikinci yakalama grubudur.
\s+ Bir veya daha fazla boşluk karakteri eşleştirin.
(\d+) Bir veya daha fazla ondalık basamağı eşleştirin. Bu, üçüncü yakalama grubudur.

Sabit bir karakter kümesi yerine desene göre bir dizeden alt dizeleri ayıklamak için normal ifade de kullanabilirsiniz. Bu, şu koşullardan herhangi biri oluştuğunda sık karşılaşılan bir senaryodur:

  • Bir veya daha fazla sınırlayıcı karakteri her zaman örnekte sınırlayıcı String olarak çalışmaz.

  • Sınırlayıcı karakterlerin sırası ve sayısı değişken veya bilinmiyor.

Örneğin, Split yöntemi, \n (yeni satır) karakterlerinin sayısı değişken olduğu ve her zaman sınırlayıcı olarak hizmet etmediği için aşağıdaki dizeyi bölmek için kullanılamaz.

[This is captured\ntext.]\n\n[\n[This is more captured text.]\n]
\n[Some more captured text:\n   Option1\n   Option2][Terse text.]

Aşağıdaki örnekte gösterildiği gibi normal bir ifade bu dizeyi kolayca bölebilir.

String input = "[This is captured\ntext.]\n\n[\n" +
               "[This is more captured text.]\n]\n" +
               "[Some more captured text:\n   Option1" +
               "\n   Option2][Terse text.]";
String pattern = @"\[([^\[\]]+)\]";
int ctr = 0;

foreach (System.Text.RegularExpressions.Match m in
   System.Text.RegularExpressions.Regex.Matches(input, pattern))
{
    Console.WriteLine($"{++ctr}: {m.Groups[1].Value}");
}

// The example displays the following output:
//       1: This is captured
//       text.
//       2: This is more captured text.
//       3: Some more captured text:
//          Option1
//          Option2
//       4: Terse text.
Dim input As String = String.Format("[This is captured{0}text.]" +
                                  "{0}{0}[{0}[This is more " +
                                  "captured text.]{0}{0}" +
                                  "[Some more captured text:" +
                                  "{0}   Option1" +
                                  "{0}   Option2][Terse text.]",
                                  vbCrLf)
Dim pattern As String = "\[([^\[\]]+)\]"
Dim ctr As Integer = 0
For Each m As Match In Regex.Matches(input, pattern)
    ctr += 1
    Console.WriteLine("{0}: {1}", ctr, m.Groups(1).Value)
Next

' The example displays the following output:
'       1: This is captured
'       text.
'       2: This is more captured text.
'       3: Some more captured text:
'          Option1
'          Option2
'       4: Terse text.

Normal ifade düzeni \[([^\[\]]+)\] şöyle tanımlanır:

Desen Açıklama
\[ Açılış parantezini eşleştirin.
([^\[\]]+) Açılış veya kapanış köşeli parantezi olmayan herhangi bir karakteri bir veya birden fazla kez eşleştirin. Bu ilk yakalama grubudur.
\] Bir kapanış parantezini eşleştirin.

Regex.Split yöntemi, sabit karakter kümesi yerine bir dizeyi normal ifade desenine göre bölmesi dışında neredeyse ile aynıdırString.Split. Örneğin, aşağıdaki örnek, çeşitli kısa çizgi ve diğer karakter bileşimleriyle sınırlandırılmış alt dizeler içeren bir dizeyi bölmek için yöntemini kullanır Regex.Split .

String input = "abacus -- alabaster - * - atrium -+- " +
               "any -*- actual - + - armoire - - alarm";
String pattern = @"\s-\s?[+*]?\s?-\s";
String[] elements = System.Text.RegularExpressions.Regex.Split(input, pattern);

foreach (string element in elements)
    Console.WriteLine(element);

// The example displays the following output:
//       abacus
//       alabaster
//       atrium
//       any
//       actual
//       armoire
//       alarm
Dim input As String = "abacus -- alabaster - * - atrium -+- " +
                    "any -*- actual - + - armoire - - alarm"
Dim pattern As String = "\s-\s?[+*]?\s?-\s"
Dim elements() As String = Regex.Split(input, pattern)
For Each element In elements
    Console.WriteLine(element)
Next

' The example displays the following output:
'       abacus
'       alabaster
'       atrium
'       any
'       actual
'       armoire
'       alarm

Normal ifade düzeni \s-\s?[+*]?\s?-\s şöyle tanımlanır:

Desen Açıklama
\s- Beyaz boşluk karakterini takip eden bir kısa çizgiyi eşleştirin.
\s? Sıfır veya bir beyaz boşluk karakterini eşleştirin.
[+*]? + veya * karakterinden herhangi birinin sıfır veya bir kere oluşabilen durumunu eşleştirin.
\s? Sıfır veya bir beyaz boşluk karakterini eşleştirin.
-\s Kısa çizgi ve ardından boşluk karakteri eşleştirin.

String.IndexOf ve String.Substring yöntemleri

Bir dizedeki tüm alt dizelerle ilgilenmiyorsanız, eşleşmenin başladığı dizini döndüren dize karşılaştırma yöntemlerinden biriyle çalışmayı tercih edebilirsiniz. Ardından istediğiniz alt dizeyi Substring ayıklamak için yöntemini çağırabilirsiniz. Dize karşılaştırma yöntemleri şunlardır:

  • IndexOf, bir karakterin veya dizenin bir dizede ilk kez geçmesinin sıfır tabanlı dizinini döndürür.

  • IndexOfAny, bir karakter dizisindeki herhangi bir karakterin ilk geçtiği geçerli dize örneğinde sıfır tabanlı dizini döndürür.

  • LastIndexOf, bir dize örneğindeki bir karakterin veya dizenin son oluşumunun sıfır tabanlı dizinini döndürür.

  • LastIndexOfAny, karakter dizisi içerisindeki herhangi bir karakterin son oluşumunun geçerli dize örneğindeki sıfır tabanlı dizinini döndürür.

Aşağıdaki örnek, dizedeki IndexOf dönemleri bulmak için yöntemini kullanır. Ardından Substring yöntemini, tam cümleleri döndürmek için kullanır.

String s = "This is the first sentence in a string. " +
               "More sentences will follow. For example, " +
               "this is the third sentence. This is the " +
               "fourth. And this is the fifth and final " +
               "sentence.";
var sentences = new List<String>();
int start = 0;
int position;

// Extract sentences from the string.
do
{
    position = s.IndexOf('.', start);
    if (position >= 0)
    {
        sentences.Add(s.Substring(start, position - start + 1).Trim());
        start = position + 1;
    }
} while (position > 0);

// Display the sentences.
foreach (var sentence in sentences)
    Console.WriteLine(sentence);

// The example displays the following output:
//       This is the first sentence in a string.
//       More sentences will follow.
//       For example, this is the third sentence.
//       This is the fourth.
//       And this is the fifth and final sentence.
    Dim input As String = "This is the first sentence in a string. " +
                        "More sentences will follow. For example, " +
                        "this is the third sentence. This is the " +
                        "fourth. And this is the fifth and final " +
                        "sentence."
    Dim sentences As New List(Of String)
    Dim start As Integer = 0
    Dim position As Integer

    ' Extract sentences from the string.
    Do
        position = input.IndexOf("."c, start)
        If position >= 0 Then
            sentences.Add(input.Substring(start, position - start + 1).Trim())
            start = position + 1
        End If
    Loop While position > 0

    ' Display the sentences.
    For Each sentence In sentences
        Console.WriteLine(sentence)
    Next
End Sub

' The example displays the following output:
'       This is the first sentence in a string.
'       More sentences will follow.
'       For example, this is the third sentence.
'       This is the fourth.
'       And this is the fifth and final sentence.

Aralıklar ve indisler

C# aralık işleci .. ve uçtan uca dizin işleci ^ , kısa bir söz dizimi kullanarak alt dizeleri ayıklamanıza olanak tanır. Bu işleçleri çağırmadan Substringdoğrudan dizelere uygulayabilirsiniz.

Aşağıdaki örnekte, aralıkları kullanarak dizenin bölümlerini ayıklamanın çeşitli yolları gösterilmektedir:

string str = "Hello, World!";

// Get the first 5 characters.
string hello = str[..5];
Console.WriteLine(hello);
// Output: Hello

// Get the last 6 characters.
string world = str[^6..];
Console.WriteLine(world);
// Output: World!

// Get characters from index 7 through 11 (exclusive of 12).
string substr = str[7..12];
Console.WriteLine(substr);
// Output: World

Sonraki örnekte, bir yoldaki dosya uzantısını (son üç karakter) kaldırmak için uçtan uca dizin işleci kullanılır:

string filePath = "C:\\Users\\user1\\bin\\fileA.cs";

// Remove the last 3 characters (.cs extension).
string trimmedPath = filePath[..^3];
Console.WriteLine(trimmedPath);
// Output: C:\Users\user1\bin\fileA

Uyarı

Aralıklar ve uçtan uca dizin işleci C# özellikleridir. Visual Basic bu söz dizimlerini desteklemez; yerine kullanın Substring .

Ayrıca bkz.