문자열 리터럴
String literal문자열 리터럴 또는 익명[1] 문자열은 컴퓨터 프로그램의 소스 코드에서 문자열 값을 표현하기 위한 리터럴의 한 종류입니다.현대 프로그래밍 언어에서 이것은 보통 다음과 같이 따옴표로 묶인 문자 시퀀스(공식적으로 "괄호 구분자")입니다.x = "foo"
,어디에"foo"
값을 가진 문자열 리터럴입니다.foo
– 따옴표는 값의 일부가 아니며 딜리미터 충돌 문제를 방지하고 딜리미터 자체를 문자열에 포함시키기 위해 이스케이프 시퀀스 등의 메서드를 사용해야 합니다.그러나 문자열 리터럴을 지정하기 위한 많은 대체 표기법이 있으며, 특히 더 복잡한 경우 정확한 표기법은 해당 개별 프로그래밍 언어에 따라 달라집니다.그럼에도 불구하고, 대부분의 현대 프로그래밍 언어들이 따르는 일반적인 가이드라인이 있습니다.
구문
괄호로 둘러싸인 구분 기호
대부분의 최신 프로그래밍 언어에서는 문자열 리터럴을 지정하기 위해 대괄호 구분 기호(균형 구분 기호도 사용)를 사용합니다.이중 따옴표는 가장 일반적으로 사용되는 따옴표 구분 기호입니다.
"안녕하세요!"
빈 문자열은 문자 그대로 따옴표 쌍으로 작성되며, 그 사이에 문자가 전혀 없습니다.
""
일부 언어에서는 이중 따옴표 대신 단일 따옴표 사용을 허용하거나 강제합니다(문자열은 같은 종류의 따옴표로 시작하고 끝나야 하며 따옴표 유형은 약간 다른 의미를 제공할 수도 있고 제공하지 않을 수도 있습니다).
"안녕하세요!
이러한 따옴표는 쌍으로 되어 있지 않습니다(같은 문자가 오프너와 클로저로 사용되고 있습니다).이것은 최초의 컴퓨터 입력 및 출력 디바이스의 선구자였던 타자기 테크놀로지에 의한 것입니다.
정규 표현에 관해서는 따옴표로 둘러싸인 기본 문자열 리터럴은 다음과 같습니다.
"[^"]*"
즉, 문자열 리터럴은 따옴표 뒤에 0, 1개 또는 여러 개의 따옴표 뒤에 따옴표로 작성됩니다.실제로는 이스케이프, 다른 딜리미터 및 줄 바꿈 제외로 인해 이 문제가 복잡해지는 경우가 많습니다.
쌍으로 구분된 구분 기호
여러 언어가 쌍으로 구분하는 문자를 제공하며, 여기서 시작 구분 기호와 닫힘 구분 기호는 다릅니다.이 경우 중첩된 문자열도 허용되므로 딜리미터가 쌍으로 되어 있는 한 딜리미터가 포함될 수 있지만 쌍으로 구성되지 않은 닫힘 딜리미터를 포함하기 위해 딜리미터 충돌이 발생합니다.예를 들어 다음과 같이 괄호를 사용하는 PostScript가 있습니다.(The quick (brown fox))
및 m4: 시작 딜리미터로 백틱(')을 사용하고 끝 딜리미터로 아포스트로피(')를 사용합니다.Tcl은 다음과 같이 따옴표(보간 문자열의 경우)와 중괄호(원시 문자열의 경우)를 모두 사용할 수 있습니다."The quick brown fox"
또는{The quick {brown fox}}
코드 블록은 Tcl 구문적으로 문자열 리터럴과 같기 때문에 Unix 쉘의 단일 따옴표와 복합문에서의 중괄호 사용에서 파생됩니다.따라서 딜리미터 쌍은 이를 실현하기 위해 필수적입니다.
유니코드 문자 집합에는 단일 따옴표와 이중 따옴표의 쌍(개시와 닫힘) 버전이 모두 포함됩니다.
"안녕하세요" "안녕하세요" "안녕하세요" "안녕하세요"
단, 많은 프로그래밍 언어가 등록하지 않기 때문에 거의 사용되지 않습니다(한 가지 예외는 Visual Basic에서 사용할 수 있는 쌍으로 이루어진 이중 따옴표입니다).NET) 호환성을 위해서는 페어링되지 않은 마크가 선호됩니다.다양한 키보드 상에서 타이핑이 용이하기 때문에 많은 프로젝트에서는 소스 코드 사용을 금지하고 있습니다.
공백 구분 기호
문자열 리터럴은 줄 바꿈으로 끝날 수 있습니다.
예를 들어 MediaWiki 템플릿파라미터가 있습니다.
{{내비게이션 이름=제목=제목=제목=제목:[computing] }}의 특수한 순서입니다.
여러 줄 문자열에는 특별한 구문이 있을 수 있습니다.
YAML에서 문자열 리터럴은 공백 및 들여쓰기의 상대적인 위치에 의해 지정될 수 있습니다.
- 직함: YAML의 여러 줄 문자열 예시 몸: 이것은 여러 줄의 문자열입니다. '특수' 메타캐릭터는 다음과 같은 경우가 있습니다. 여기에 표시됩니다.이 문자열의 범위는 움푹 패임으로 표현됩니다.
구분자 없음
Perl 및 PHP와 같은 일부 프로그래밍 언어는 일부 컨텍스트에서 구분 기호 없이 문자열 리터럴을 허용합니다.예를 들어 다음 Perl 프로그램에서는red
,green
,그리고.blue
는 스트링 리터럴이지만 따옴표로 묶지 않습니다.
%map = (빨간. => 0x00f, 파랑색 => 0x0f0, 초록의 => 0xf00);
Perl은 대부분의 컨텍스트에서 예약되지 않은 영숫자 시퀀스를 문자열 리터럴로 취급합니다.예를 들어 다음 두 줄의 Perl이 동일합니다.
$y = "x"; $y = x;
선언적 표기법
원래의 FORTRAN 프로그래밍 언어(예를 들어)에서는 문자열 리터럴은 이른바 Hollerith 표기법으로 작성되었습니다.여기서 문자수의 10진수 뒤에 문자 H가 이어지며 문자열의 문자가 이어집니다.
35한 예 홀리스 스트링 문자 그대로의
이 선언적 표기 스타일은 문자열 양쪽에 균형 잡힌 "괄호" 문자를 사용할 필요가 없기 때문에 괄호 구분 기호 따옴표와 대조됩니다.
장점:
- ( 딜리미터 문자에 대한) 텍스트 검색이 불필요하므로 오버헤드가 대폭 줄어듭니다.
- 딜리미터 충돌 문제를 회피합니다.
- 명령어로 오인될 수 있는 메타문자를 포함할 수 있도록 합니다.
- 플레인 텍스트[citation needed] 문자열의 매우 효과적인 데이터 압축에 사용할 수 있습니다.
결점:
- 이 표기는 프로그래머가 수동으로 입력하는 경우 오류가 발생하기 쉽다
- 멀티바이트 인코딩의 경우 특별한 주의가 필요합니다.
단,[citation needed] 대부분의 경우처럼 알고리즘에 의해 프리픽스가 생성되는 경우에는 이것이 단점이 되지 않습니다.
생성자 함수
C++에는 2가지 스타일의 문자열이 있습니다.하나는 C에서 상속됩니다(구분)."
더 안전합니다.std::string
C++ 표준 라이브러리로 이동합니다.그std::string
클래스는 문자열 리터럴이 다른 언어에서 사용되는 것과 동일한 방식으로 자주 사용되며 유연성과 안전성이 뛰어나기 때문에 종종 C 스타일 문자열보다 선호됩니다.하지만 스트링 리터럴에 대해서는 퍼포먼스 패널티가 부과됩니다.std::string
는 보통 메모리를 동적으로 할당하고 실행 시 C 스타일 문자열 리터럴을 복사해야 합니다.
C++11 이전에는 C++ 문자열용 리터럴이 없었습니다(C++11에서는 가능)."this is a C++ string"s
와 함께s
리터럴의 말미에)가 있기 때문에 일반 컨스트럭터 구문이 사용되었습니다.다음은 예를 제시하겠습니다.
std::string str = "initializer syntax";
std::string str("converting constructor syntax");
std::string str = string("explicit constructor syntax");
모두 같은 해석을 하고 있습니다.C++11 이후 새로운 컨스트럭터 구문도 있습니다.
std::string str{"uniform initializer syntax"};
auto str = "constexpr literal syntax"s;
구분자 충돌
따옴표를 사용할 때 딜리미터 자체를 문자열 리터럴로 나타내려면 딜리미터 충돌 문제가 발생합니다.예를 들어 딜리미터가 큰따옴표인 경우 단순히 큰따옴표 자체를 리터럴로 나타낼 수 없습니다."""
두 번째 따옴표는 문자열 값이 아닌 문자열 리터럴의 끝으로 해석되며 마찬가지로 쓸 수 없습니다."This is "in quotes", but invalid."
가운데 인용된 부분은 인용문의 외부로 해석되기 때문입니다.다양한 솔루션이 있으며 가장 일반적인 목적은 다음과 같은 이스케이프 시퀀스를 사용하는 것입니다."\""
또는"This is \"in quotes\" and properly escaped."
, 그러나 다른 많은 해결책이 있습니다.
Tcl의 중괄호와 같은 따옴표를 쌍으로 사용하면 다음과 같은 중첩된 문자열을 사용할 수 있습니다.{foo {bar} zork}
단, 다음과 같이 불균형 클로징 딜리미터를 단순히 포함할 수 없기 때문에 딜리미터 충돌 문제를 해결하지 마십시오.{}}
.
더블업
Pascal, BASIC, DCL, Smalltalk, SQL, J, Fortran 등 다수의 언어는 문자열 리터럴 자체의 일부로 간주되는 따옴표를 두 배로 하여 딜리미터 충돌을 방지합니다.
'이 파스칼 문자열'''2개의 아포스트로피를 포함하다'''
"내 말 들려?"""
이중 견적
Fortran, Modula-2, JavaScript, Python 및 PHP와 같은 일부 언어에서는 여러 개의 따옴표 딜리미터를 사용할 수 있습니다. 두 개의 딜리미터를 사용할 수 있는 경우 이를 이중 따옴표라고 합니다.일반적으로 이것은 프로그래머가 단일 따옴표 또는 이중 따옴표 중 하나를 서로 바꾸어 사용할 수 있도록 하는 것으로 구성됩니다. 각 리터럴은 둘 중 하나를 사용해야 합니다.
"이것은 존의 사과입니다." "내 말 들려?""'
단, 양쪽 딜리미터를 모두 포함하는 단일 리터럴은 사용할 수 없습니다.이 문제는 여러 리터럴과 문자열 연결을 사용하여 해결할 수 있습니다.
'이거'라고 했더니 + '존스 + 사과."'
Python은 문자열 리터럴 연결을 가지고 있기 때문에 연산자가 없어도 연속 문자열 리터럴이 연결되므로 다음과 같이 줄일 수 있습니다.
'이거'라고 했더니'존스사과."'
D는 몇 개의 따옴표 딜리미터를 지원하며,q"[
으로 끝나다]"
또는 다른 딜리미터 문자([] <> {} 또는 [] 중 하나)에 대해서도 마찬가지입니다.또한 D는 유사한 구문을 통해 문서 형식의 문자열을 지원합니다.
sh 및 Perl과 같은 일부 프로그래밍 언어에는 문자열 보간 실행 여부 등 다르게 취급되는 여러 딜리미터가 있으므로 사용할 딜리미터를 선택할 때 주의해야 합니다.아래의 다른 종류의 스트링을 참조하십시오.
복수 견적
또한 여러 따옴표를 사용하여 문자열 리터럴의 경계를 지정할 문자를 선택할 수 있습니다.
예를 들어 Perl의 경우:
"내 말 들려?"라고 물었더니^ qq@"내 말 들려요?"@ "내 말 들려?"라고 물었더니§
모두 원하는 결과를 얻을 수 있습니다.이 표기법은 보다 유연하지만 Perl, Ruby(Perl의 영향을 받은) 및 C++11 이외에는 이를 지원하는 언어가 거의 없습니다.C++11 에서는, raw 문자열에는, 다음의 다양한 딜리미터를 사용할 수 있습니다.R"delimiter(
으로 끝나다)delimiter"
딜리미터의 길이는 0 ~16 문자이며, 공백 문자, 괄호 또는 백슬래시를 제외한 기본 소스 문자 집합의 멤버를 포함할 수 있습니다.여러 따옴표의 변형으로는 문서 형식의 문자열을 사용하는 방법이 있습니다.
Lua(5.1 기준)에서는 특히 긴 주석이나 삽입 문자열을 중첩할 수 있도록 제한된 형식의 여러 견적을 제공합니다.보통 사용하는 것은[[
그리고.]]
리터럴 스트링(첫 번째 줄 바꿈, 또는 raw)을 구분합니다만, 여는 괄호에는 임의의 수의 등호를 포함할 수 있습니다.따라서 같은 수의 기호가 있는 닫는 괄호만 문자열을 닫습니다.예를 들어 다음과 같습니다.
현지의 이요 = [=[ 이 표기법은 Windows 패스에 사용할 수 있습니다. 로컬 경로 = [[C:\Windows\글꼴]] ]=]
따옴표와 같은 일반 구분 기호를 포함하는 정규 표현식에서 여러 개의 따옴표는 특히 유용합니다. 이렇게 하면 따옴표가 이스케이프되지 않아도 됩니다.초기 예로는 sed가 있습니다.여기서 substitution 명령어는s/regex/replacement/
디폴트 슬래시/
딜리미터는 다른 문자로 대체할 수 있습니다.s,regex,replacement,
.
생성자 함수
현대 언어에서는 거의 사용되지 않는 또 다른 옵션은 문자열을 리터럴을 통해 표현하는 것이 아니라 문자열을 구성하는 함수를 사용하는 것입니다.계산은 해석 시간이 아닌 실행 시간에 이루어지기 때문에 일반적으로 현대 언어에서는 사용되지 않습니다.
예를 들어 BASIC의 초기 형식에는 이스케이프 시퀀스나 여기에 열거된 다른 회피책이 포함되어 있지 않기 때문에 대신 다음 중 하나를 사용해야 합니다.CHR$
function : 인수에 대응하는 문자를 포함하는 문자열을 반환합니다.ASCII에서 따옴표는 값 34를 가지므로 ASC에서 따옴표로 문자열을 나타냅니다.II 시스템 1은 쓸 것이다.
나는 말했다, " + CHR$(34) + "내 말 들려?" + CHR$(34)
C 에서는, 다음의 방법으로 같은 설비를 이용할 수 있습니다.sprintf
및 그%c
"character" 형식 지정자는 다른 회피책에서는 일반적으로 사용되지 않습니다.
스프린트(%cin 인용문입니다.%c", 34, 34);
일반적으로 이스케이프 시퀀스가 대신 사용되지만 이러한 컨스트럭터 함수는 인쇄되지 않은 문자를 나타내기 위해 사용할 수도 있습니다.C++ 에서도 같은 기술을 사용할 수 있습니다.std::string
문자열화 연산자.
이스케이프 시퀀스
이스케이프 시퀀스는 딜리미터, 비인쇄 문자(백스페이스 등), 줄바꿈 문자, 공백 문자(시각적으로 구별할 수 없는 문자) 등 직접 표현하기 어려운 문자를 표현하기 위한 일반적인 기술입니다.따라서 이들은 문자열 리터럴에서 널리 사용되며 이스케이프 시퀀스를 추가하는 것(단일 문자 또는 문자열 전체에 추가)을 이스케이프라고 합니다.
직접 포함하기 어렵거나 불가능한 문자에 대한 인코딩을 제공하기 위해 접두사로 한 문자가 선택됩니다.일반적으로 이것은 백슬래시입니다.다른 문자와 더불어 백슬래시 자체를 이중 백슬래시로 인코딩할 수 있는 것이 포인트입니다.\\
구분된 문자열의 경우 딜리미터 자체를 이스케이프(excape)함으로써 부호화할 수 있습니다.\"
의 경우, 이러한 이스케이프 스트링의 정규 표현은 ANSI C [2][a]사양에서 볼 수 있듯이 다음과 같이 지정할 수 있습니다.
"(\\. [^\\"])*"
"따옴표"는 "따옴표 뒤에 0 이상의 이스케이프 문자(백슬래시 뒤에 무엇인가, 백슬래시 또는 따옴표로 끝남), 또는 따옴표로 끝나지 않은 따옴표와 백슬래시 앞에 이어지는 따옴표를 구분하는 데에만 문제가 있습니다.백슬래시 뒤에 여러 문자를 사용할 수 있습니다.\uFFFF
이스케이프 스킴에 따라 달라집니다.
그런 다음 이스케이프 문자열 자체를 사전 분석하여 이스케이프된 문자열을 나타내는 이스케이프되지 않은 문자열로 변환해야 합니다.이것은 컴퓨터 언어의 전체 어휘화의 평가 단계에서 이루어진다: 전체 언어의 어휘자의 평가자는 이스케이프된 문자열 리터럴에 대해 자체 어휘자를 실행한다.
특히 일반적으로 문자열 상수를 종료하는 문자를 부호화할 수 있어야 하며 이스케이프 문자 자체를 지정하는 방법이 있어야 합니다.이스케이프 시퀀스가 항상 예쁘거나 사용하기 쉬운 것은 아니기 때문에 많은 컴파일러가 일반적인 문제를 해결하는 다른 방법을 제공합니다.그러나 이스케이프 시퀀스는 모든 딜리미터 문제를 해결하고 대부분의 컴파일러는 이스케이프 시퀀스를 해석합니다.이스케이프 문자가 문자열 리터럴 안에 있는 경우 "이것이 이스케이프 시퀀스의 시작"을 의미합니다.모든 이스케이프 시퀀스는 문자열에 직접 배치되는1개의 문자를 지정합니다.이스케이프 시퀀스에 필요한 실제 문자 수는 다릅니다.이스케이프 문자는 키보드의 맨 위/왼쪽에 있지만 편집자가 번역하기 때문에 문자열로 직접 테이핑할 수 없습니다.백슬래시는 문자열 리터럴의 이스케이프 문자를 나타내기 위해 사용됩니다.
많은 언어가 문자열 리터럴에 메타문자를 사용할 수 있도록 지원합니다.메타문자는 문맥과 언어에 따라 해석이 다르지만 일반적으로 인쇄 또는 비인쇄 문자를 나타내기 위한 일종의 '처리 명령어'입니다.
예를 들어 C 문자열 리터럴에서 백슬래시 뒤에 "b", "n" 또는 "t"와 같은 문자가 있으면 각각 인쇄되지 않은 백스페이스, 줄바꿈 또는 탭 문자를 나타냅니다.또는 백슬래시 뒤에 1 ~3의 8진수가 이어지는 경우 이 시퀀스는 지정된 ASCII 코드로 임의의 문자를 나타내는 것으로 해석됩니다.이것은 나중에 확장되어 보다 현대적인 16진수 문자 코드 표기법을 사용할 수 있게 되었습니다.
나는 말했다.\t\t\x22Ca내 말 들려?\x22\n"
이스케이프 시퀀스 | 유니코드 | 문자열에 삽입된 리터럴 문자 |
---|---|---|
\0 | U+0000 | 늘 문자[3][4] (일반적으로 \oo 8진 표기의 특수한 경우) |
\a | U+0007 | 경계[5][6]. |
\b | U+0008 | 백스페이스[5] |
\f | U+000C | 형틀[5] 피드 |
\n | U+000A | 회선[5] 피드(또는 POSIX에서는 newline) |
\r | U+000D | 캐리지[5] 리턴(또는 Mac OS 9 이전 버전에서는 새로운 라인) |
\t | U+0009 | 수평[5] 탭 |
\v | U+000B | 세로[5] 탭 |
\e | U+001B | 이스케이프[6] 문자(GCC,[7] clang 및 tcc) |
\u#### | U+##### | 16비트 Unicode 문자 (####은 4자리 16진수[4]) |
\U######## | U+###### | ###############은 8자리 16진수입니다(유니코드 문자 공간은 현재 폭이 21비트이므로 처음 두 자리 16진수는 항상 0입니다). |
\u{#####} | U+###### | 21비트의 Unicode 문자(######은 가변 16진수) |
\x## | U+00## | 8비트 문자 사양(#은 16진수[5]) |
\ooo | U+0#### | 8비트 문자 사양(o는 8진수[5]) |
\" | U+0022 | 큰따옴표(")[5] |
\& | Haskell에서[3] 숫자 이스케이프를 구분하는 데 사용되는 문자가 아닙니다. | |
\' | U+0027 | 작은따옴표(')[5] |
\\ | U+005C | 백슬래시(\)[5] |
\? | U+003F | 물음표(?)[5] |
주의: 목록 내의 모든 시퀀스가 모든 파서에서 지원되는 것은 아니며 목록에 없는 다른 이스케이프 시퀀스가 있을 수 있습니다.
중첩 이스케이프
어떤 프로그래밍 언어의 코드가 다른 프로그래밍 언어에 포함되어 있는 경우 삽입된 문자열은 여러 단계의 이스케이프를 필요로 할 수 있습니다.이는 다른 언어 또는 셸 스크립트 내의 다른 언어에서의 정규 표현 및 SQL 쿼리에서 특히 일반적입니다.이 이중 이스케이프는 종종 읽고 쓰기가 어렵다.
중첩된 문자열을 잘못 따옴표로 묶으면 보안 취약성이 발생할 수 있습니다.SQL 쿼리의 데이터 필드에서와 같이 신뢰할 수 없는 데이터를 사용하는 경우 코드 주입 공격을 방지하기 위해 준비된 문을 사용해야 합니다.PHP 2에서 5.3까지는 매직쿼트라고 불리는 기능이 있어 편리성과 보안을 위해 자동으로 스트링을 이스케이프했습니다만, 5.4 이후 버전에서는 문제로 인해 삭제되었습니다.
원시 문자열
일부 언어에서는 리터럴을 언어 고유의 해석 없이 처리하도록 지정하는 방법을 제공합니다.이를 통해 탈출할 필요가 없어지고 읽기 쉬운 문자열이 생성됩니다.
raw 문자열은 공통 문자를 이스케이프해야 할 경우 특히 백슬래시가 있는 정규 표현(문자열 리터럴로 내포됨)에서 유용합니다.\
는 널리 사용되며 DOS/Windows 경로에서는 백슬래시가 경로 구분자로 사용됩니다.백슬래시의 풍부함은 기울어진 이쑤시개 증후군으로 알려져 있으며, 생현을 사용함으로써 줄일 수 있다.C#의 이스케이프 패스명과 raw 패스명을 비교합니다.
"Windows 경로는 C:\\입니다.Foo\\Bar\Baz\\" @" Windows 패스는 C:\Foo\Bar\Baz\
이 두 가지를 조합하면 극단적인 예가 발생합니다.– 균일한 명명 규칙 경로는 다음과 같이 시작됩니다.\\
UNC 이름에 일치하는 이스케이프 정규 표현은 8개의 백슬래시로 시작합니다."\\\\\\\\"
스트링과 정규 표현을 이스케이프할 필요가 있기 때문입니다.raw 문자열을 사용하면 C#과 같이 이 값이 4(정규 표현에서는 이스케이프)로 감소합니다.@"\\\\"
.
XML 문서에서는 CDATA 섹션을 사용하여 & 및 < 등의 문자를 XML 파서로 해석하지 않고 사용할 수 있습니다.이것은 리터럴 텍스트와 스크립팅 코드를 포함할 때 문서의 형식을 잘 유지하기 위해 유용합니다.
<![CDATA[if (패스!= add & depth <2> {add(path); } ] >
여러 줄의 문자열 리터럴
많은 언어에서 문자열 리터럴은 여러 줄에 걸쳐 리터럴 줄바꿈을 포함할 수 있습니다.또는 대부분의 경우 다음과 같이 새 행을 이스케이프할 수 있습니다.\n
. 예:
메아리치다 '후우' 바'
그리고.
echo - e "foo\nbar"
둘 다 유효한 bash입니다.생성:
푸바
리터럴 줄바꿈을 사용할 수 있는 언어에는 bash, Lua, Perl, PHP, R 및 Tcl이 있습니다.일부 다른 언어에서는 문자열 리터럴에 줄바꿈을 포함할 수 없습니다.
여러 줄 문자열 리터럴의 두 가지 문제는 줄 바꿈과 들여쓰기입니다.첫 번째 또는 마지막 딜리미터가 다른 행에 있는 경우 추가 새 행이 있는 반면 그렇지 않은 경우 딜리미터는 문자열을 읽기 어렵게 만듭니다.특히 첫 번째 행은 다른 행과 다르게 들여쓰기됩니다.또한 선두 공백이 유지되므로 리터럴은 의도하지 않아야 합니다.리터럴이 들여쓰기된 코드 내에서 발생할 경우 코드의 흐름이 중단됩니다.
이러한 문제에 대한 가장 일반적인 해결책은 문서 형식의 문자열 리터럴입니다.공식적으로 말하면, 여기서 문서는 문자열 리터럴이 아니라 스트림 리터럴 또는 파일 리터럴입니다.이들은 셸 스크립트에서 생성되며 외부 명령어에 대한 입력으로 리터럴을 공급할 수 있습니다.첫 번째 딜리미터는<<END
어디에END
임의의 단어가 될 수 있으며 닫힘 딜리미터는 다음과 같습니다.END
그 자체로 콘텐츠 경계로서 기능하고 있습니다.<<
리터럴에서 stdin을 리다이렉트하기 때문입니다.딜리미터는 임의이기 때문에 딜리미터의 충돌 문제도 회피할 수 있습니다.이를 통해 변형 구문을 통해 초기 탭을 제거할 수도 있습니다.<<-END
선두 공간은 제거되지 않습니다.같은 구문이 여러 언어의 문자열 리터럴(특히 Perl)에 채택되어 여기에서 문서라고도 불리며 문자열이며 리다이렉션을 수반하지 않는 경우에도 구문은 유지됩니다.다른 문자열 리터럴과 마찬가지로 변수 보간 등 지정된 동작이 다를 수 있습니다.
일반적인 문자열 리터럴에서는 리터럴한 줄 바꿈을 허용하지 않는 Python은 대신 트리플 따옴표라고 불리는 여러 줄 리터럴용으로 설계된 특별한 문자열 형식을 가지고 있습니다.이것들은 3배의 딜리미터를 사용합니다.'''
또는"""
이러한 리터럴은 docstring이라고 불리는 인라인 문서 작성에 특히 사용됩니다.
Tcl은 문자열 내에서 리터럴한 줄바꿈을 허용하며 여러 줄의 문자열을 지원하는 특별한 구문은 없습니다.단, 딜리미터는 줄바꿈 자체와 줄바꿈 및 줄바꿈을 생략할 수 있습니다.string trim
,하는 동안에string map
움푹 패인 부분을 제거하는 데 사용할 수 있습니다.
문자열 리터럴 연결
몇몇 언어는 문자열 리터럴 연결을 제공하며, 여기서 인접한 문자열 리터럴은 컴파일 시 암묵적으로 단일 리터럴에 결합됩니다.이것은 [8][9][14]C에서 복사한 C,[10] C++,[11][12] D, Ruby, [13]Python의 기능입니다.특히, 이 연결은 사전 분석 중 컴파일 시간에 발생하며(초기 토큰화 이후의 단계로서), 양쪽 런타임 문자열 연결과 대조됩니다(일반적으로,+
연산자)[15] 및 연속 폴딩 중 연결은 컴파일 시 발생하지만 이후 단계(구절 분석 또는 "구절" 이후)에 발생합니다.C#, Java[16] 및 Perl 등 대부분의 언어는 암묵적인 문자열 리터럴 연결을 지원하지 않으며 대신 다음과 같이 명시적인 연결을 필요로 합니다.+
연산자(이것은 D 및 Python에서도 가능하지만 C/C++에서는 불법입니다). 이 경우 연결은 컴파일 시, 지속적인 폴딩을 통해 발생하거나 실행 시 지연될 수 있습니다.
동기
개념과 용어가 유래한 C에서는 스트링 리터럴 연결이 다음 두 가지 [17]이유로 도입되었습니다.
- 들여쓰기 방식을 파괴하는 행 연속과 대조적으로 긴 문자열이 여러 행에 걸쳐 적절한 들여쓰기를 허용한다.
- 매크로에 의한 스트링 리터럴의 작성을 가능하게 한다(스트링화에 의한).[18]
실용적인 측면에서, 이것은 구문 분석이나 지속적인 접힘 없이 편집의 초기 단계("번역", 특히 어휘 분석의 일부로서)에서 문자열 연결을 가능하게 한다.예를 들어 유효한 C/C++는 다음과 같습니다.
차 *s = "안녕하세요" "세계"; 인쇄물("안녕하세요" "세계");
단, 다음 항목은 유효하지 않습니다.
차 *s = "안녕하세요" + "세계"; 인쇄물("안녕하세요" + "세계");
그 이유는 문자열 리터럴에는 어레이 타입이 있기 때문입니다.char [n]
(C) 또는const char [n]
(C++), 이것은 추가할 수 없습니다.다른 대부분의 언어에서는 제한이 없습니다.
이것은 특히 [14]매크로에서 전처리 후에 스트링을 계산할 수 있도록 하기 위해 C 프리프로세서와 조합하여 사용하는 경우 특히 중요합니다.예를 들어 다음과 같습니다.
차 *file_and_message = __FILE__ ": 메시지";
(파일이 a.c인 경우)는 다음과 같이 전개됩니다.
차 *file_and_message = 교류 ": 메시지";
그 후 연결되며, 이는 다음과 같습니다.
차 *file_and_message = "A.C: 메시지";
일반적인 사용 사례는 printf 또는 scanf 형식 문자열을 구성하는 것입니다. 여기서 형식 지정자는 [19][20]매크로에 의해 지정됩니다.
보다 복잡한 예에서는 (프리프로세서에 의한) 정수의 문자열화를 사용하여 일련의 문자열 리터럴로 전개되는 매크로를 정의하고, 그 매크로를 파일명과 행 [21]번호를 사용하여 단일 문자열 리터럴로 연결합니다.
#정의 STRINGIFY(x) #x #정의 TOSTRING(x) STRINGIFY(x) #정의 AT __FILE__": 토스트링(_LINE__)
C/C++의 구문요건을 넘어 암묵적 연결은 구문설탕의 한 형태로 문자열 리터럴을 여러 줄에 걸쳐 쉽게 분할할 수 있으므로 (백슬래시를 통해) 행 연속이 필요하지 않으며 문자열의 일부에 주석을 추가할 수 있습니다.예를 들어 Python에서는 다음과 같은 방법으로 [22]정규 표현식에 주석을 달 수 있습니다.
참조..컴파일하다([A-Za-z_] # 글자 또는 밑줄 [A-Za-z0-9_]*" 문자, 숫자 또는 밑줄 수 )
문제
암묵적인 문자열 연결은 지속적인 폴딩을 구현하는 최신 컴파일러에서는 필요하지 않으며, 다음과 같이 쉼표를 생략한 의도하지 않은 연결로 인해 다음과 같은 오류가 발생합니다.
l = ['푸', '바' 'zork']
따라서 대부분의 언어에서 사용되지 않으며 D와 [14]Python에서 폐지될[23] 것으로 제안되었습니다.단, 기능을 삭제하면 하위 호환성이 깨지고 연결 연산자로 대체하면 우선순위의 문제가 발생합니다.문자열 리터럴 연결은 연산자 평가 전에 렉싱 중에 발생하지만 명시적 연산자를 통한 연결은 다른 연산자와 동시에 발생하므로 우선순위가 문제가 됩니다.ll 원하는 평가 순서를 확인하기 위해 괄호가 필요합니다.
하위 문제는 C와 C++[24]에는 다양한 유형의 문자열 리터럴이 있으며 이들 스트링 리터럴을 연결하면 구현 정의 동작이 있어 잠재적인 보안 [25]위험이 발생한다는 것입니다.
다양한 종류의 문자열
일부 언어는 여러 종류의 리터럴을 제공하며 동작은 다릅니다.이것은 특히 원시 문자열(이탈 없음)을 나타내거나 변수 보간을 비활성화 또는 활성화하기 위해 사용되지만 문자 집합을 구별하는 등 다른 용도로 사용됩니다.대부분의 경우 따옴표 문자를 변경하거나 접두사 또는 접미사를 추가하여 이 작업을 수행합니다.이는 16진수나 긴 정수를 나타내는 것과 같은 정수 리터럴에 대한 접두사 및 접미사에 해당합니다.
가장 오래된 예 중 하나는 셸 스크립트에서 작은 따옴표는 원시 문자열 또는 "리터럴 문자열"을 나타내며 큰 따옴표는 이스케이프 시퀀스와 변수 보간입니다.
예를 들어, Python에서는 raw 문자열 앞에 raw 문자열이 있습니다.r
또는R
– 비교'C:\\Windows'
와 함께r'C:\Windows'
(단, Python raw 문자열은 홀수 백슬래시로 끝날 수 없습니다).Python 2는 또한 두 가지 유형의 문자열을 구분합니다: 8비트 ASCII("바이트") 문자열(기본값).b
또는B
프리픽스 및 Unicode 스트링으로 표시됩니다.u
또는U
prefix.[26] 반면 Python 3 문자열은 기본적으로 Unicode이고 바이트는 별개입니다.bytes
따옴표로 초기화할 때 접두사가 앞에 와야 하는 유형b
.
원시 문자열의 C# 표기법은 @-quoting이라고 불립니다.
@"C:\Foo\Bar\Baz"
이것에 의해 이스케이프가 디세이블이 되는 한편, 이중 따옴표를 사용할 수 있습니다.따옴표는 문자열 내에서 다음과 같습니다.
@"안녕하세요."""
C++11 에서는, 프리픽스에 의해서 결정되는 미가공 문자열, Unicode 문자열(UTF-8, UTF-16, 및 UTF-32) 및 와이드 문자열을 사용할 수 있습니다.또한 기존 C++에 대한 리터럴을 추가합니다.string
일반적으로 기존 C 스타일 문자열보다 선호됩니다.
Tcl에서는 괄호로 구분된 문자열은 리터럴이며 따옴표로 구분된 문자열은 이스케이프 및 보간입니다.
Perl에는 다양한 문자열이 있습니다.이 문자열은 보다 공식적으로 연산자로 간주되며 인용 연산자와 인용 연산자로 알려져 있습니다.여기에는 통상의 구문(고정 구분자)과 범용 구문이 모두 포함되어 구분자를 선택할 수 있습니다.이러한 구문은 다음과 같습니다.[27]
'' "" `` // m// qr// s// y/// q{} q{} qx{} qw{} m{} qr{} s{}{} tr{}{} y{}{}
REXX 에서는, 서픽스 문자를 사용하고, 문자 또는 문자열을 16 진수 코드 또는 바이너리 코드로 지정합니다.예.,
'20'x '0010 0000' b '00100000' b
모두 공백 문자를 생성하여 함수 호출을 회피합니다.X2C(20)
.
문자열 보간
일부 언어에서는 문자열 리터럴에 현재 컨텍스트에서 평가되는 변수 또는 식을 참조하는 자리 표시자가 포함될 수 있습니다(일반적으로 실행 시).이를 변수 보간, 더 일반적으로 문자열 보간이라고 합니다.보간을 지원하는 언어는 일반적으로 보간된 문자열 리터럴과 그렇지 않은 문자열을 구분합니다.예를 들어 sh 호환 Unix 쉘(Perl 및 Ruby)에서는 이중 따옴표(따옴표로 구분됨, ") 문자열은 보간되지만 단일 따옴표로 구분됨(apostrophe 구분됨, ") 문자열은 보간되지 않습니다.비간접 문자열 리터럴은 "원문자열"이라고 불리기도 하지만, 이는 탈출이라는 의미에서 "원문자열"과는 다릅니다.예를 들어 Python에서는 앞에 다음 문자열이 붙습니다.r
또는R
에는 이스케이프 또는 보간 기능이 없습니다.일반 문자열(프리픽스 없음)에는 이스케이프는 있지만 보간 기능은 없습니다.또한 프리픽스에는 프리픽스가 붙어 있습니다.f
또는F
탈출과 보간 기능이 있어요
예를 들어 다음과 같은 Perl 코드입니다.
이름 = "낸시'; $140 = '헬로 월드'; 인쇄물 "$name은 군중에게 $1,000를 지불했습니다.";
는 다음과 같은 출력을 생성합니다.
낸시는 군중들에게 헬로 월드라고 말했다.
이 경우 메타문자($)는 변수 할당문의 기호와 혼동하지 않도록 해석되며 문자 그대로 출력해야 할 경우 일부 이스케이프가 필요합니다.
이것은, 다음의 경우와 대조할 필요가 있습니다.printf
함수는 다음과 같은 표기법을 사용하여 동일한 출력을 생성합니다.
인쇄물 %s는 군중에게 %s라고 말했습니다., 이름, $140;
단, 보간은 실행하지 않습니다.%s
는 printf 형식 문자열의 플레이스 홀더이지만 변수 자체는 문자열 외부에 있습니다.
이는 "raw" 문자열과 대조됩니다.
인쇄물 '$name은 군중에게 $1,000이라고 말했다.';
다음과 같은 출력이 생성됩니다.
$name은 군중에게 $1,000를 주었다.
여기서 $문자는 메타문자가 아니며 일반 텍스트 이외의 의미는 없습니다.
문자열 리터럴에 소스 코드 포함
문자열 리터럴을 지정할 수 있는 유연성이 부족한 언어는 다른 프로그래밍 코드를 생성하는 프로그래밍 코드를 작성하는 것을 특히 번거롭게 합니다.이는 특히 세대 언어가 출력 언어와 같거나 유사한 경우에 해당됩니다.
예를 들어 다음과 같습니다.
- 퀴즈를 만들기 위한 코드 작성
- 웹 템플릿 내에서 출력 언어 생성
- XSLT를 사용하여 XSLT를 생성하거나 SQL을 사용하여 더 많은 SQL을 생성하거나
- C 또는 기타 언어로 작성된 문서 처리 응용 프로그램 내에서 인쇄를 위해 문서의 PostScript 표현을 생성합니다.
- 필기 셰이더
그럼에도 불구하고, 일부 언어들은 특히 딜리미터 충돌을 피하기 위한 여러 옵션을 지원하는 이러한 종류의 자기 유사 출력을 생성하기 위해 잘 적응되어 있습니다.
문자열 리터럴을 다른 코드를 생성하는 코드로 사용하면 특히 출력이 적어도 부분적으로 신뢰할 수 없는 사용자 입력에 기초하는 경우 보안에 악영향을 미칠 수 있습니다.이는 악의적인 사용자가 이러한 약점을 이용하여 SQL 주입 공격 등을 통해 응용 프로그램의 동작을 전복시킬 수 있는 웹 기반 응용 프로그램의 경우 특히 심각합니다.
「 」를 참조해 주세요.
메모들
- ^ 여기에 제시된 정규식은 혼동을 줄이기 위해 인용되거나 이스케이프되지 않습니다.
레퍼런스
- ^ "Introduction To Java - MFC 158 G".
String literals (or constants) are called ‘anonymous strings’
- ^ "ANSI C grammar (Lex)". liu.se. Retrieved 22 June 2016.
- ^ a b "Appendix B. Characters, strings, and escaping rules". realworldhaskell.org. Retrieved 22 June 2016.
- ^ a b "String". mozilla.org. Retrieved 22 June 2016.
- ^ a b c d e f g h i j k l m "Escape Sequences (C)". microsoft.com. Retrieved 22 June 2016.
- ^ a b "Rationale for International Standard - Programming Languages - C" (PDF). 5.10. April 2003. pp. 52, 153–154, 159. Archived (PDF) from the original on 2016-06-06. Retrieved 2010-10-17.
- ^ "6.35 The Character <ESC> in Constants", GCC 4.8.2 Manual, retrieved 2014-03-08
- ^ C11 초안 표준, WG14 N1570 위원회 초안 - 2011년 4월 12일, 5.1.1.2 번역 단계, 페이지 11: "6.인접한 문자열 리터럴 토큰이 연결됩니다."
- ^ C 구문: 문자열 리터럴 연결
- ^ C++11 초안 표준, 2.2 번역 단계 [lex.phase], 페이지 17: "6.인접한 스트링 리터럴 토큰은 연결되어 있습니다." 및 2.14.5 스트링 리터럴[lex.string ], 주 13, 페이지 28-29: "변환 단계 6(2.2)에서는 인접한 스트링 리터럴이 연결되어 있습니다."
- ^ D 프로그래밍 언어, Lexical Analysis, "String Literals": "인접 문자열은 ~ 연산자와 연결되거나 단순 병렬로 연결됩니다."
- ^ ruby: The Ruby Programming Language, Ruby Programming Language, 2017-10-19, retrieved 2017-10-19
- ^ Python Language Reference, 2. Lexical Analysis, 2.4.2. 문자열 리터럴 연결: "여러 인접 문자열 리터럴(공백으로 구분됨)이 허용되며, 다른 따옴표 규칙을 사용할 수 있으며, 그 의미는 연결과 동일합니다."
- ^ a b c Python-ideas, "암묵적인 문자열 문자 그대로 연결은 유해하다고 간주됩니까?", Guido van Rossum, 2013년 5월 10일
- ^ Python Language Reference, 2. Lexical Analysis, 2.4.2. 문자열 리터럴 연결: "이 기능은 구문 수준에서 정의되지만 컴파일 시 구현됩니다.실행 시 문자열 식을 연결하는 데 '+' 연산자를 사용해야 합니다."
- ^ "Strings (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)". Docs.oracle.com. 2012-02-28. Retrieved 2016-06-22.
- ^ 3.1.4 스트링 리터럴Rationale for the ANSI C Programming Language. Silicon Press. 1990. p. 31. ISBN 0-929306-07-4.: "backslash-newline continuation을 사용하여 여러 줄에 걸쳐 긴 스트링을 계속할 수 있지만, 이 방법에서는 스트링의 연속이 다음 줄의 첫 번째 위치에서 시작되어야 합니다.보다 유연한 레이아웃을 허용하고 몇 가지 전처리 문제를 해결하기 위해 위원회는 문자열 문자 그대로 연결을 도입했다(제3.8.3절 참조).2개의 스트링 리터럴을 한 줄에 붙여(중간에 늘 문자를 포함하지 않음) 하나의 스트링 리터럴을 조합합니다.C언어에 이 추가에 의해 프로그래머는 백슬래시-뉴라인 메커니즘을 사용하지 않고 물리적인 줄의 끝을 넘어 문자열 리터럴을 확장하여 프로그램의 들여쓰기 방식을 파괴할 수 있습니다.명시적 연결 연산자는 런타임 연산이 아닌 어휘적 구조이기 때문에 도입되지 않았습니다."
- ^ Rationale for the ANSI C Programming Language. Silicon Press. 1990. p. 6566. ISBN 0-929306-07-4., 3.8.3.2 # 연산자: "# 연산자는 문자열화를 위해 도입되었습니다.#define 확장에서만 사용할 수 있습니다.이 명령어를 사용하면 형식 파라미터명이 실제 인수 토큰시퀀스를 문자열화하여 형성된 문자열 리터럴로 대체됩니다.스트링 리터럴 연결과 함께(「3.1.4」 참조) 이 연산자를 사용하면 스트링 내의 식별자 치환에 의한 것처럼 효과적으로 스트링을 구성할 수 있습니다.이 기준서의 예는 이 기능을 보여줍니다."
- ^ C/C++ 사용자 저널, 제19권, 페이지 50
- ^ "python - Why allow concatenation of string literals?". Stack Overflow. Retrieved 2016-06-22.
- ^ "LINE__ to string (stringify) using preprocessor directives". Decompile.com. 2006-10-12. Retrieved 2016-06-22.
- ^ Python Language Reference, 2. Lexical Analysis, 2.4.2. 문자열 리터럴 연결: "이 기능은 필요한 백슬래시의 수를 줄이거나 긴 문자열을 긴 행으로 편리하게 분할하거나 문자열의 일부에 주석을 추가하는 데 사용할 수 있습니다. 예를 들어 다음과 같습니다.
- ^ DLang의 문제 추적 시스템– 제3827호 - 인접한 문자열 리터럴의 암묵적인 연계에 대해 경고 및 권장 해제
- ^ C++11 초안 표준, 2.14.5 문자열 리터럴 [lex.string], 주 13, 페이지 28-29: "기타 연결은 구현 정의 동작으로 조건부로 지원됩니다."
- ^ "Archived copy". Archived from the original on July 14, 2014. Retrieved July 3, 2014.
{{cite web}}
: CS1 maint: 제목으로 아카이브된 복사(링크) - ^ "2. Lexical analysis — Python 2.7.12rc1 documentation". python.org. Retrieved 22 June 2016.
- ^ "perlop - perldoc.perl.org". perl.org. Retrieved 22 June 2016.