인문주의 사피엔스

Flutter/Dart에서 문자열을 쪼개는 방법 본문

프로그래밍/Flutter

Flutter/Dart에서 문자열을 쪼개는 방법

인문주 2022. 5. 14. 19:07
반응형

다음 코드는 알파벳(a, b), 특수 문자(?, !, [, ], \), 유니코드(👀)를 포함하는 문자열 string을 정의합니다.

 

  const string = r'a?  b! [👀]\';

 

여기서 문자열 맨앞에 붙은 r은 raw를 뜻합니다. r을 붙인 문자열은 '있는 그대로의 날것'으로 취급됩니다. 날것으로 취급되면 백슬래시(\)에 의한 회피(escape) 기능이 작동하지 않습니다. 예를 들어 r'a\nb'를 print하면 다음과 같이 한 줄로 출력됩니다.

 

print(r'a\nb')

a\nb

 

하지만 r을 제거하면 백슬래시(\)에 의한 회피 기능이 작동됩니다. 백슬래시는 알파벳 n의 문자로서의 기능을 회피하고 '새 줄'이라는 기능을 부여합니다. 그래서 'a\nb'를 print하면 다음과 같이 두 줄로 출력됩니다.

 

print('a\nb')

a

b

 

다음 코드의 함수 check는 string의 내용과 길이를 표시합니다.

 

  void check(int number, var object) => print('#$number $object (${object.length})');
  check(0, string);

 

string의 길이는 다음과 같이 12로 표시됩니다. 

 

I/flutter ( 3055): #0 a?  b! [👀]\ (12)

 

길이 12는 다음과 같이 계산됩니다.

 

  • 아스키 코드 7개: a?b![ ]\
  • 공백 3개:
  • 2바이트 크기 유니코드 1개: 👀

 

String.split을 사용해 문자열을 개별 문자로 쪼개기

split 함수에 빈 문자를 입력하면 string에 포함된 모든 개별 문자가 배열 형태로 반환됩니다.

 

  check(1, string.split(‘'));

 

그런데 실행 결과는 예상과 조금 다릅니다. 유니코드(👀)가 표시되지 않습니다.

 

I/flutter ( 3055): #1 [a, ?,  ,  , b, !,  , [, , , ], \] (12)

 

그 이유는 String 클래스가 문자열을 UTF-16 형식으로 처리하기 때문입니다. 따라서 반환된 배열에는 유니코드 👀의 코드 값 U+1F440이 UTF-16 형식으로 변환된 D83D와 DC40이 담깁니다. 하지만 D83D와 DC40은 문자로 출력될 수 없습니다. print 함수가 UTF-16 형식을 사용하지 않기 때문입니다.

 

유니코드를 제대로 이해하는 방법

 

유니코드를 제대로 이해하는 방법

유니코드(Unicode)는 컴퓨터에서 체계적이고 통일된 방식으로 문자를 처리하기 위해 만든 국제 기술 표준입니다. 유니코드가 널리 사용되면서 관련 업종 종사자 이외의 일반 사용자들도 유니코드

theoryof0.tistory.com

 

String.characters 사용하기

유니코드를 제대로 표시하려면 Characters 클래스를 사용해야 합니다.

 

  check(2, string.characters.toList());

 

Characters 클래스는 다음과 같이 유니코드를 정상적으로 표시합니다. 대신 배열의 크기는 12가 아니라 11이 되었습니다. 유니코드가 하나의 문자로 계산되기 때문입니다.

 

I/flutter ( 3055): #2 [a, ?,  ,  , b, !,  , [, 👀, ], \] (11)

 

다음 코드처럼 배열에서 공백 문자를 제외할 수도 있습니다.

 

 check(3, string.characters.toList()..removeWhere((e) => e == ' ‘));

 

공백 문자를 제외하면 문자의 수는 8이 됩니다.

 

I/flutter ( 3055): #3 [a, ?, b, !, [, 👀, ], \] (8)

 

 

반응형

 

String.split을 사용해 문자열을 단어로 쪼개기

split 함수에 공백을 사용하면 개별 문자가 이닌 단어를 추출할 수 있습니다. 

 

  check(4, string.split(' ‘));

 

결과는 다음과 같이 두 공백 사이의 빈 문자를 포함하여 4개의 단어로 분리됩니다.

 

I/flutter ( 3055): #4 [a?, , b!, [👀]\] (4)

 

여기서 만약 ?, !, [, ], \ 등의 특수 문자를 제외하려면 어떻게 해야 할까요? 각강의 단어를 검사해서 특수 문자를 제거하는 방법도 있지만 정규 표현(regular expression)을 사용하면 더 간단하게 처리할 수도 있습니다.

 

Flutter/Dart에서 정규 표현식(Regular Expression) 사용하기

 

Flutter/Dart에서 정규 표현식(Regular Expression) 사용하기

정규 표현식은 문자열을 정해진 규칙에 따라 표현한 것을 뜻하며 다음 요소들을 조합하여 구성됩니다. 일반 문자(character) a-z A-Z 0-9 메타 문자(metacharacter) ., \d, \D, \s, \S, \w, \W 연산자(operator) +, *, ?

theoryof0.tistory.com

 

정규 표현식(RegExp)을 사용해 문자열을 단어로 쪼개기

정규 표현식을 사용하는 아래의 코드는 앞에서 String.split을 사용한 경우와 결과가 같습니다.

 

  check(5, string.split(RegExp(r'[ ]’)));

 

I/flutter ( 3055): #5 [a?, , b!, [👀]\] (4)

 

공백 사이에 있는 빈 문자를 제거할 수 있습니다.

 

  check(6, string.split(RegExp(r'[ ]'))..removeWhere((e) => e.isEmpty));

 

 

I/flutter ( 3055): #6 [a?, b!, [👀]\] (3)

 

다음과 같이 특수 문자 ?와 !를 제거할 수도 있습니다.

 

  check(7, string.split(RegExp(r'[ ?!]'))..removeWhere((e) => e.isEmpty));

 

I/flutter ( 3055): #7 [a, b, [👀]\] (3)

 

다음은 나머지 특수 문자까지 모두 제거하는 코드입니다. 특수 문자 [, ], \의 경우 이미 특정 용도로 지정되어 있기 때문에 앞에 백슬래시(\)를 붙여 기능을 회피(escape)해야 합니다.

 

  check(8, string.split(RegExp(r'[ ?!\[\]\\]'))..removeWhere((e) => e.isEmpty));

 

 

I/flutter ( 3055): #8 [a, b, 👀] (3)

 

다음은 전체 소스코드입니다.

 

void test() {
  void check(int number, var object) => print('#$number $object (${object.length})');

  const string = r'a?  b! [👀]\';
  check(0, string);
  check(1, string.split(''));

  check(2, string.characters.toList());
  check(3, string.characters.toList()..removeWhere((e) => e == ' '));

  check(4, string.split(' '));
  check(5, string.split(RegExp(r'[ ]')));
  check(6, string.split(RegExp(r'[ ]'))..removeWhere((e) => e.isEmpty));

  check(7, string.split(RegExp(r'[ ?!]'))..removeWhere((e) => e.isEmpty));
  check(8, string.split(RegExp(r'[ ?!\[\]\\]'))..removeWhere((e) => e.isEmpty));
}

 

 

반응형
Comments