문자열에서 부분 문자열 추출

이 문서에서는 문자열의 일부를 추출하는 몇 가지 방법을 설명합니다.

  • 원하는 부분 문자열이 알려진 구분 문자(또는 문자)로 구분된 경우 Split 메서드를 사용합니다.
  • 정규식은 문자열이 고정 패턴을 준수하는 경우에 유용합니다.
  • 문자열의 모든 부분 문자열을 추출하려는 것이 아니라면 IndexOf 메서드와 Substring 메서드를 함께 사용하세요.

String.Split 메서드

String.Split은 지정하는 하나 이상의 구분 문자에 따라 문자열을 부분 문자열 그룹으로 분할하는 데 도움이 되는 몇 가지 오버로드를 제공합니다. 최종 결과에서 전체 부분 문자열 수를 제한하거나, 부분 문자열에서 공백 문자를 자르거나, 빈 부분 문자열을 제외할 수 있습니다.

다음 예제는 String.Split()의 세 가지 오버로드를 보여 줍니다. 첫 번째 예제는 구분 문자를 전달하지 않고 Split(Char[]) 오버로드를 호출합니다. 구분 문자를 지정하지 않으면 String.Split()은 공백 문자인 기본 구분 기호를 사용하여 문자열을 분할합니다.

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.

여기에서 볼 수 있듯이 마침표 문자(.)가 두 부분 문자열에 포함됩니다. 마침표 문자를 제외하려는 경우 마침표 문자를 추가 구분 문자로 추가할 수 있습니다. 다음 예제는 이 작업을 수행하는 방법을 보여 줍니다.

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:

부분 문자열에서 마침표가 사라졌지만 이제는 두 개의 빈 부분 문자열이 추가로 포함되었습니다. 이러한 빈 부분 문자열은 단어와 그 뒤에 오는 마침표 사이의 부분 문자열을 나타냅니다. 결과 배열에서 빈 부분 문자열을 생략하려면 Split(Char[], StringSplitOptions) 오버로드를 호출하고 options 매개 변수의 StringSplitOptions.RemoveEmptyEntries을 지정합니다.

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

정규식

문자열이 고정 패턴을 따르는 경우 정규식을 사용하여 해당 요소를 추출하고 처리할 수 있습니다. 예를 들어 문자열이 "숫자피연산자숫자" 형식을 사용하는 경우 정규식을 사용하여 문자열의 요소를 추출하고 처리할 수 있습니다. 예를 들면 다음과 같습니다.

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("{0} = {1}", m.Value, value1 + value2);
                break;
            case "-":
                Console.WriteLine("{0} = {1}", m.Value, value1 - value2);
                break;
            case "*":
                Console.WriteLine("{0} = {1}", m.Value, value1 * value2);
                break;
            case "/":
                Console.WriteLine("{0} = {1:N2}", m.Value, value1 / value2);
                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

정규식 패턴 (\d+)\s+([-+*/])\s+(\d+)는 다음과 같이 정의됩니다.

패턴 설명
(\d+) 하나 이상의 10진수 숫자가 일치하는지 확인합니다. 이 그룹은 첫 번째 캡처링 그룹입니다.
\s+ 하나 이상의 공백 문자를 찾습니다.
([-+*/]) 산술 연산자 기호(+, -, *, /)를 찾습니다. 이 그룹은 두 번째 캡처링 그룹입니다.
\s+ 하나 이상의 공백 문자를 찾습니다.
(\d+) 하나 이상의 10진수 숫자가 일치하는지 확인합니다. 이 그룹은 세 번째 캡처링 그룹입니다.

정규식을 사용하여 고정 문자 집합이 아닌 패턴을 기반으로 문자열에서 부분 문자열을 추출할 수도 있습니다. 다음은 이러한 조건 중 하나가 발생하는 일반적인 시나리오입니다.

  • 하나 이상의 구분 문자가 String 인스턴스에서 항상 구분 기호로 사용되지는 않습니다.

  • 구분 문자의 시퀀스와 수는 변수이거나 알 수 없습니다.

예를 들어 Split 메서드는 다음 문자열을 분할하는 데 사용할 수 없습니다. \n(줄 바꿈) 문자 수가 변수이고 이 문자가 항상 구분 기호로 사용되지는 않기 때문입니다.

[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 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("{0}: {1}", ++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.

정규식 패턴 \[([^\[\]]+)\]는 다음과 같이 정의됩니다.

패턴 설명
\[ 여는 대괄호를 찾습니다.
([^\[\]]+) 여는 대괄호나 닫는 대괄호가 아닌 문자를 한 번 이상 찾습니다. 이 그룹은 첫 번째 캡처링 그룹입니다.
\] 닫는 대괄호를 찾습니다.

Regex.Split 메서드는 고정 문자 집합 대신 정규식 패턴을 기반으로 문자열을 분할한다는 점을 제외하면 String.Split과 거의 동일합니다. 예를 들어 다음 예제에서는 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

정규식 패턴 \s-\s?[+*]?\s?-\s는 다음과 같이 정의됩니다.

패턴 설명
\s- 뒤에 하이픈이 오는 공백 문자를 찾습니다.
\s? 0번 이상 나오는 공백 문자를 찾습니다.
[+*]? 0번 또는 한 번 나오는 + 또는 * 문자를 찾습니다.
\s? 0번 이상 나오는 공백 문자를 찾습니다.
-\s 뒤에 공백 문자가 오는 하이픈을 찾습니다.

String.IndexOf 및 String.Substring 메서드

문자열의 모든 부분 문자열에 관심이 있는 것이 아니라면 일치가 시작되는 인덱스를 반환하는 문자열 비교 메서드 중 하나를 사용하는 것이 좋습니다. 그런 다음 Substring 메서드를 호출하여 원하는 부분 문자열을 추출할 수 있습니다. 문자열 비교 메서드는 다음과 같습니다.

  • 문자열 인스턴스에서 처음 나오는 문자 또는 문자열의 0부터 시작하는 인덱스를 반환하는 IndexOf

  • 문자 배열에서 문자가 처음 나오는 현재 문자열 인스턴스의 0부터 시작하는 인덱스를 반환하는 IndexOfAny

  • 문자열 인스턴스에서 마지막으로 나오는 문자 또는 문자열의 0부터 시작하는 인덱스를 반환하는 LastIndexOf

  • 문자 배열에서 문자가 마지막으로 나오는 현재 문자열 인스턴스의 0부터 시작하는 인덱스를 반환하는 LastIndexOfAny

다음 예제는 IndexOf 메서드를 사용하여 문자열의 마침표를 찾습니다. 그런 다음 Substring 메서드를 사용하여 전체 문장을 반환합니다.

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.

참고 항목