F# 문자열

F# 문자열 (Strings)

F#의 string 타입은 수정할 수 없는(immutable) 텍스트를 유니코드 문자 시퀀스로 표현해요. .NET에서 이 stringSystem.String의 별칭(alias)이라서, .NET이 제공하는 문자열 기능을 그대로 다 쓸 수 있어요. 이번 글에서는 F# 문자열 리터럴을 작성하는 여러 방법과 이스케이프 시퀀스, 인덱싱·슬라이싱, 문자열을 다루는 연산자·모듈을 하나씩 살펴볼게요.

출처: https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/strings

본문

문자열 리터럴과 이스케이프 시퀀스 (String literals and escape sequences)

문자열 리터럴은 따옴표(") 문자로 감싸서 표현해요. 백슬래시 문자(\)는 특정 특수 문자를 표현하는 데 사용되는데, 이 백슬래시와 그다음에 오는 문자를 합쳐서 **이스케이프 시퀀스(escape sequence)**라고 불러요. F# 문자열 리터럴에서 지원되는 이스케이프 시퀀스는 다음 표와 같아요.

문자 이스케이프 시퀀스
경고음 (Alert) \a
백스페이스 (Backspace) \b
용지 넘김 (Form feed) \f
줄바꿈 (Newline) \n
캐리지 리턴 (Carriage return) \r
탭 (Tab) \t
세로 탭 (Vertical tab) \v
백슬래시 (Backslash) \\
따옴표 (Quotation mark) \"
아포스트로피 (Apostrophe) \'
유니코드 문자 \DDD (D는 십진수 한 자리; 범위는 000 - 255; 예: \231 = "ç")
유니코드 문자 \xHH (H는 16진수 한 자리; 범위는 00 - FF; 예: \xE7 = "ç")
유니코드 문자 \uHHHH (UTF-16) (H는 16진수 한 자리; 범위는 0000 - FFFF; 예: \u00E7 = "ç")
유니코드 문자 \U00HHHHHH (UTF-32) (H는 16진수 한 자리; 범위는 000000 - 10FFFF; 예: \U0001F47D = "👽")

중요 \DDD 이스케이프 시퀀스는 대부분의 다른 언어처럼 8진수가 아니라 10진수 표기예요. 그래서 숫자 8과 9도 유효하며, \032는 공백(U+0020)을 나타내요. 같은 코드 포인트를 8진수로 표기하면 \040이 되는 것과 대비돼요.

참고 \DDD\x 이스케이프 시퀀스는 범위가 0 - 255(0xFF)로 제한되는데, 이는 유니코드의 첫 256개 코드 포인트와 정확히 일치하므로 실질적으로 ISO-8859-1 문자 집합을 뜻해요.

베르바팀 문자열 (Verbatim strings)

리터럴 앞에 @ 기호가 붙으면 그 문자열은 **베르바팀 문자열(verbatim string)**이 돼요. 베르바팀 문자열을 선언하면 모든 이스케이프 시퀀스가 무시되는데, 단 두 개의 따옴표 문자가 연속으로 오는 경우에는 하나의 따옴표 문자로 해석돼요.

삼중 따옴표 문자열 (Triple quoted strings)

한편 문자열을 삼중 따옴표로 감쌀 수도 있어요. 이 경우에는 큰따옴표 문자를 포함한 모든 이스케이프 시퀀스가 무시돼요. 문자열 안에 따옴표가 내장된 문자열을 표현해야 할 때는 베르바팀 문자열이나 삼중 따옴표 문자열 중 하나를 사용할 수 있어요. 베르바팀 문자열을 사용하면 하나의 따옴표 문자를 나타내기 위해 따옴표 문자를 두 번 적어야 하지만, 삼중 따옴표 문자열을 사용하면 따옴표 문자가 문자열의 끝으로 해석될 걱정 없이 그냥 한 번만 적으면 돼요. 이런 방식은 XML이나 그 밖에 따옴표가 내장된 구조를 다룰 때 특히 유용해요.

// Using a verbatim string
let xmlFragment1 = @"<book author=""Milton, John"" title=""Paradise Lost"">"

// Using a triple-quoted string
let xmlFragment2 = """<book author="Milton, John" title="Paradise Lost">"""

코드에서는 줄바꿈이 포함된 문자열도 허용돼요. 단, 줄바꿈 바로 앞 문자가 백슬래시가 아닌 이상, 줄바꿈은 소스 코드에서 사용된 줄바꿈 인코딩 그대로 해석돼요. 그리고 백슬래시를 사용한 경우에는 다음 줄의 앞부분 공백은 무시돼요. 아래 코드는 값이 "abc\n def"인 문자열 str1과 값이 "abcdef"인 문자열 str2를 만들어요.

let str1 =
    "abc
     def"

let str2 =
    "abc\
     def"

문자열 인덱싱과 슬라이싱 (String indexing and slicing)

배열처럼 생긴 문법을 사용하면 문자열의 개별 문자에 접근할 수 있어요. 다음 예시들은 []를 사용해 문자열을 인덱싱해요. 이 문법은 F# 6.0에서 도입됐으며, 모든 버전에서는 .[] 문법도 사용할 수 있어요. 새 문법을 사용하는 편이 권장돼요.

printfn "%c" str1[1]

출력 결과는 b예요.

또는 배열 슬라이스 문법을 사용해서 부분 문자열(substring)을 추출할 수도 있어요. 다음 코드가 그 예시예요.

printfn "%s" str1[0..2]
printfn "%s" str2[3..5]

출력 결과는 다음과 같아요.

abc
def

ASCII 문자열은 부호 없는 바이트 배열, 즉 byte[] 타입으로 표현할 수 있어요. 문자열 리터럴에 B 접미사를 붙이면 그 문자열이 ASCII 문자열임을 나타내요. 바이트 배열과 함께 쓰이는 ASCII 문자열 리터럴은 유니코드 이스케이프 시퀀스를 제외하고는 유니코드 문자열과 동일한 이스케이프 시퀀스를 지원해요.

// "abc" interpreted as a Unicode string.
let str1: string = "abc"
// "abc" interpreted as an ASCII byte array.
let bytearray: byte[] = "abc"B

문자열 연산자 (String operators)

+ 연산자를 사용하면 문자열을 이어 붙일(concatenate) 수 있어요. 이는 .NET Framework의 문자열 처리 기능과의 호환성을 유지하기 위한 것이에요. 다음 예시가 문자열 연결을 보여줘요.

let string1 = "Hello, " + "world"

String 클래스 (The String class)

F#의 string 타입은 실제로 .NET Framework의 System.String 타입이므로, System.String의 모든 멤버를 사용할 수 있어요. System.String에는 문자열을 연결하는 데 쓰이는 + 연산자, Length 프로퍼티, 그리고 문자열을 유니코드 문자 배열로 반환하는 Chars 프로퍼티가 포함돼요. 문자열에 대해 더 자세히 알고 싶다면 System.String을 참고해요.

System.StringChars 프로퍼티를 사용하면 다음 코드처럼 인덱스를 지정해서 문자열의 개별 문자에 접근할 수 있어요.

let printChar (str: string) (index: int) =
    printfn "First character: %c" (str.Chars(index))

String 모듈 (The String module)

문자열 처리를 위한 추가 기능은 FSharp.Core 네임스페이스의 String 모듈에 들어 있어요. 자세한 내용은 String Module을 참고해요.

더 알아보기 (Learn more)