히어 도큐먼트
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
히어 도큐먼트는 유닉스 셸 스크립트에서 사용되는 기능으로, 특정 구분자를 사용하여 여러 줄의 텍스트를 정의하는 방식이다. 텍스트를 명령의 입력으로 전달하거나 파일처럼 사용할 수 있으며, 다양한 프로그래밍 언어에서도 유사한 기능을 제공한다. 변수 확장, 명령 치환 등의 기능을 지원하며, 여러 줄의 문자열을 간편하게 처리할 수 있게 해준다.
히어 도큐먼트는 파일 리터럴 또는 스트림 리터럴로, 유닉스 셸에서 기원한 기능이다.[27] sh, Bash, ksh, zsh 등 다양한 유닉스 셸에서 사용할 수 있으며[2], 명령어의 표준 입력으로 여러 줄의 텍스트를 직접 전달하는 데 사용된다.
히어 도큐먼트는 본래 유닉스 셸에서 유래한 파일 리터럴 또는 스트림 리터럴의 한 형태이지만, 현대의 많은 프로그래밍 언어에서도 유사한 기능을 다양한 방식으로 지원한다. 이러한 기능은 주로 여러 줄에 걸친 문자열 리터럴을 편리하게 작성하기 위해 사용된다. "세는 항상 이보다 크다, --작가 미상
2. 유닉스 셸
일반적으로 `<<` 연산자 뒤에 특정 구분자를 지정하여 시작하고, 다음 줄부터 내용을 입력한 뒤, 맨 마지막 줄에 시작 시 사용한 구분자만 다시 입력하여 종료하는 방식으로 사용한다. 예를 들어, `tr` 명령어처럼 표준 입력을 받는 명령어에 텍스트를 전달할 때 유용하다.
# 간단한 히어 도큐먼트 예시
$ cat << MY_DELIMITER
> 이것은 히어 도큐먼트의
> 예시입니다.
MY_DELIMITER
이것은 히어 도큐먼트의
예시입니다.
히어 도큐먼트 내부에서는 기본적으로 변수 확장이나 명령어 치환이 이루어지며, 구분자를 따옴표로 묶어 이를 제어할 수 있다. 또한 `<<-` 연산자를 사용하면 각 줄 앞부분의 탭 문자를 무시하여 셸 스크립트 내에서 들여쓰기를 유지하는 데 도움을 준다.[5] 이러한 확장 및 제어 기능, 그리고 구체적인 사용법에 대한 자세한 내용은 하위 섹션에서 다룬다.
또한 Bash, ksh, zsh 등 일부 셸에서는 `<<<` 연산자를 사용하는 '''히어 스트링'''이라는 유사한 기능도 제공하는데, 이는 단일 문자열을 표준 입력으로 전달하는 더 간결한 방법이다. 히어 스트링에 대한 자세한 내용 역시 하위 섹션에서 설명한다.
2. 1. 기본 사용법
히어 도큐먼트(Here Document)는 여러 줄의 문자열을 셸 스크립트나 특정 명령어의 표준 입력으로 직접 전달하는 방식이다.[27][2] 줄 바꿈이나 공백 등이 입력된 그대로 적용되며, 표준 입력을 처리할 수 있는 명령어와 함께 사용해야 한다. 예를 들어, tr 명령어처럼 표준 입력을 받아 처리하는 명령어에 텍스트를 전달할 때 유용하다.
가장 일반적인 사용법은 `<<` 기호 뒤에 원하는 구분 문자를 지정하고, 다음 줄부터 전달할 텍스트를 입력한 뒤, 마지막 줄에 앞에서 지정한 구분자만 단독으로 입력하여 종료하는 방식이다.
다음은 히어 도큐먼트를 사용하여 텍스트를 tr 명령어(소문자를 대문자로 변환)에 전달하는 예시이다. 이 코드는 셸 스크립트 파일에 작성하거나, 터미널 프롬프트에서 직접 입력할 수 있다.
$ LANG=C tr a-z A-Z << END_TEXT
> one two three
> four five six
> END_TEXT
ONE TWO THREE
FOUR FIVE SIX
위 예시에서 `END_TEXT`가 구분자로 사용되었다. 이 구분자는 히어 도큐먼트의 시작과 끝을 표시한다. 리다이렉션 기호 `<<`와 구분자 사이에는 공백이 있어도 되고 없어도 된다. 즉, `<
기본적으로 히어 도큐먼트 내부의 텍스트는 큰따옴표(" ")로 묶인 문자열과 유사하게 처리된다. 즉, 변수 이름(예: `$PWD`)은 해당 값으로 치환되고, 백틱(` `)으로 묶인 명령어(예: `` `pwd` ``)는 실행 결과로 치환된다.[3]
$ cat << EOF
> 현재 작업 디렉토리: "$PWD" 와 `pwd`
> EOF
현재 작업 디렉토리: "/home/user" 와 /home/user
만약 변수 확장이나 명령어 치환을 원하지 않는다면, 시작 부분의 구분자를 작은따옴표(' ')나 큰따옴표(" ")로 묶어주면 된다. 특히 작은따옴표로 묶으면(`'EOF'`) 내부 텍스트는 작은따옴표로 묶인 문자열처럼 처리되어 아무런 확장도 일어나지 않는다.[4]
$ cat << 'EOF'
> 현재 작업 디렉토리: "$PWD" 와 `pwd`
> EOF
현재 작업 디렉토리: "$PWD" 와 `pwd`
참고로, 큰따옴표로 구분자를 묶는 경우(`"EOF"`)는 일반적인 큰따옴표 문자열 처리와 달리 확장이 일어나지 않으므로 혼동을 줄 수 있다.[4]
POSIX 셸(csh/tcsh 제외)에서는 `<<` 대신 `<<-` 를 사용하면 히어 도큐먼트 내용 각 줄의 앞부분에 있는 탭 문자들이 무시된다.[5] 이를 통해 셸 스크립트 내에서 코드의 들여쓰기를 유지하면서 히어 도큐먼트를 깔끔하게 작성할 수 있다. (단, 탭이 아닌 공백은 무시되지 않는다.)
# <<- 를 사용하여 앞부분의 탭 문자를 무시하는 예시
# (아래 예시에서 각 줄 앞에는 실제 탭 문자가 있다고 가정)
LANG=C tr a-z A-Z <<- END_TEXT
one two three
four five six
END_TEXT
# 출력 결과:
# ONE TWO THREE
# FOUR FIVE SIX
# << 를 사용하면 탭 문자가 그대로 전달된다.
LANG=C tr a-z A-Z << END_TEXT
one two three
four five six
END_TEXT
# 출력 결과:
# ONE TWO THREE
# FOUR FIVE SIX
히어 도큐먼트는 명령어의 입력뿐만 아니라 파일로 직접 내용을 저장하는 데에도 사용할 수 있다.
$ cat << EOF > my_file.txt
> 이 내용은 my_file.txt 파일에 저장됩니다.
> 여러 줄을 입력할 수 있습니다.
> 앞에 탭이 있어도 그대로 저장됩니다. (<<- 사용 안 함)
EOF
히어 도큐먼트는 sh, csh, ksh, Bash, zsh 등 다양한 유닉스 셸 뿐만 아니라 Perl, PHP, Python, Ruby 같은 스크립트 언어에서도 지원된다.
2. 2. 확장 및 제어
기본적으로 히어 도큐먼트 내에서는 변수의 이름이 값으로 대체되고, 백틱(` `` `) 안의 명령어는 실행 결과로 치환되는 등 이중 인용 부호 안에서와 유사하게 동작한다.[3]
$ cat << EOF
> \$ Working dir "$PWD" `pwd`
> EOF
$ Working dir "/home/user" /home/user
이러한 확장 기능은 구분 식별자를 따옴표로 감싸서 비활성화할 수 있다. 예를 들어 작은따옴표로 구분 식별자를 감싸면, 히어 도큐먼트의 내용은 작은따옴표로 묶인 문자열처럼 처리되어 변수나 명령어가 확장되지 않는다.
$ cat << 'EOF'
> \$ Working dir "$PWD" `pwd`
> EOF
\$ Working dir "$PWD" `pwd`
큰따옴표로 구분 식별자를 감쌀 수도 있지만, 일반적인 큰따옴표 문자열 안에서는 확장이 일어나는 것과 달리 히어 도큐먼트에서는 확장이 일어나지 않기 때문에 혼동을 일으킬 수 있다.[4]
POSIX 셸(csh/tcsh 제외)에서는 리다이렉션 연산자를 <<-
와 같이 마이너스 기호(-)와 함께 사용하면, 히어 도큐먼트 내용 각 줄의 맨 앞에 있는 탭 문자가 무시된다.[5] 또한, 종료 구분자가 포함된 줄의 선행 탭 문자도 무시된다. 이를 통해 셸 스크립트 내에서 코드의 들여쓰기를 유지하면서 히어 도큐먼트를 사용할 수 있다.
다음 스크립트는 <<-
사용 여부에 따른 차이를 보여준다. (예제 코드의 들여쓰기는 실제 탭 문자로 가정한다.)
# <<- 사용: 내용 및 종료 구분자의 선행 탭 무시
LANG=C tr a-z A-Z <<- END_TEXT
Here doc with <<-
A single space character (i.e. 0x20 ) is at the beginning of this line
This line begins with a single TAB character i.e 0x09 as does the next line
END_TEXT # 이 줄의 선행 탭도 무시됨
echo The intended end was before this line
echo and these were not processed by tr
echo +++++++++++++++
# << 사용: 선행 탭 유지 (종료 구분자 앞의 탭 때문에 인식 못 함)
LANG=C tr a-z A-Z << END_TEXT
Here doc with <<
A single space character (i.e. 0x20 ) is at the beginning of this line
This line begins with a single TAB character i.e 0x09 as does the next line
END_TEXT # 이 줄 앞의 탭 때문에 구분자로 인식되지 않음
echo The intended end was before this line,
echo but because the line with the delimiting Identifier began with a TAB it was NOT recognized and
echo the tr command continued processing.
위 스크립트 실행 결과는 다음과 같다.
HERE DOC WITH <<-
A SINGLE SPACE CHARACTER (I.E. 0X20 ) IS AT THE BEGINNING OF THIS LINE
THIS LINE BEGINS WITH A SINGLE TAB CHARACTER I.E 0X09 AS DOES THE NEXT LINE
The intended end was before this line
and these were not processed by tr
+++++++++++++++
HERE DOC WITH <<
A SINGLE SPACE CHARACTER (I.E. 0X20 ) IS AT THE BEGINNING OF THIS LINE
THIS LINE BEGINS WITH A SINGLE TAB CHARACTER I.E 0X09 AS DOES THE NEXT LINE
END_TEXT # 이 줄 앞의 탭 때문에 구분자로 인식되지 않음
ECHO THE INTENDED END WAS BEFORE THIS LINE,
ECHO BUT BECAUSE THE LINE WITH THE DELIMITING IDENTIFIER BEGAN WITH A TAB IT WAS NOT RECOGNIZED AND
ECHO THE TR COMMAND CONTINUED PROCESSING.<<-
를 사용한 첫 번째 경우는 내용과 종료 구분자의 선행 탭이 모두 제거되어 tr
명령어가 정상적으로 처리되고 종료된다. 반면, <<
를 사용한 두 번째 경우는 종료 구분자 END_TEXT
앞의 선행 탭이 유지되어 셸이 이를 구분자로 인식하지 못한다. 결과적으로 tr
명령어는 스크립트의 나머지 부분까지 입력으로 받아 처리하게 된다.
2. 3. 히어 스트링
'''히어 스트링'''은 bash, ksh, zsh 셸에서 사용할 수 있는 기능으로, 구문상 히어 도큐먼트와 유사하다. 히어 스트링은 `<<<` 연산자를 사용하여 단어(word)나 문자열 리터럴을 명령어의 표준 입력으로 전달한다. 히어 스트링 자체는 특별한 종류의 문자열이 아니라, 입력 리디렉션에 사용되는 일반적인 문자열이다.
한 단어로 이루어진 경우 따옴표 없이 사용할 수 있다.
$ LANG=C tr a-z A-Z <<< one
ONE
문자열에 공백이 포함된 경우에는 따옴표로 묶어야 한다.
$ LANG=C tr a-z A-Z <<< 'one two three'
ONE TWO THREE
변수에 저장된 문자열을 사용할 수도 있다.
$ foo='one two three'
$ LANG=C tr a-z A-Z <<< "$foo"
ONE TWO THREE
여러 줄로 이루어진 문자열도 전달할 수 있다.
$ LANG=C tr a-z A-Z <<< 'one
> two three'
ONE
TWO THREE
히어 스트링은 문자열 앞뒤의 줄 바꿈 문자도 그대로 포함하여 전달한다.
$ LANG=C tr a-z A-Z <<< '
> one
> two three
> '
ONE
TWO THREE
$
히어 도큐먼트와의 주된 차이점은 구분 기호(delimiter)를 사용하지 않는다는 점과, 히어 도큐먼트처럼 문자열 앞뒤의 줄 바꿈 문자를 제거하지 않는다는 점이다.
히어 스트링은 bc와 같이 짧은 입력을 자주 받는 명령어에 특히 유용하다.
$ bc <<< 2^10
1024
히어 스트링의 동작은 파이프라인과 echo 명령어를 통해서도 유사하게 구현할 수 있다.
$ echo 'one two three' | LANG=C tr a-z A-Z
ONE TWO THREE
하지만 히어 스트링은 마지막 명령어가 현재 셸 프로세스에서 실행되어야 할 때 특히 유용하다. 예를 들어, read 내장 명령어는 표준 입력으로부터 값을 읽어와 현재 셸의 변수에 할당하는데, 파이프라인을 사용하면 `read` 명령어가 서브셸(subshell)에서 실행되기 때문에 현재 셸의 변수에 값을 할당할 수 없다.
파이프라인을 사용한 경우:
$ echo 'one two three' | read -r a b c
$ echo "$a $b $c"
위 예시는 아무것도 출력하지 않는다. 파이프라인으로 연결된 `read`는 서브셸에서 실행되어 변수 `a`, `b`, `c`에 값을 할당하지만, 이 변경 사항은 부모 셸(현재 셸)에 영향을 주지 않기 때문이다.
히어 스트링을 사용한 경우:
$ read -r a b c <<< 'one two three'
$ echo "$a $b $c"
one two three
히어 스트링을 사용하면 `read` 명령어가 현재 셸에서 실행되므로, 변수 `a`, `b`, `c`에 값이 올바르게 할당되고 출력된다.
3. 프로그래밍 언어
유닉스 셸에서의 히어 도큐먼트 구문은 일반적으로 `<<` 뒤에 구분자를 명시하고, 다음 줄부터 문자열 내용을 작성한 뒤, 마지막 줄에 해당 구분자만 다시 입력하여 종료하는 방식이다. 이 구문은 셸의 입력 리디렉션 구문(`< 파일명`)과 유사하며, 히어 도큐먼트의 내용은 종종 이전 명령어나 현재 스크립트의 표준 입력(stdin)으로 전달된다.
다른 프로그래밍 언어에서는 "히어 도큐먼트" 또는 "히어 스트링"이라는 용어를 사용하며, 펄, PHP, 루비 등이 대표적이다. 이들 언어에서는 셸의 `<<` 구문을 차용하는 경우가 많지만, 이것이 반드시 입력 리디렉션을 의미하지는 않고 단순히 여러 줄 문자열 리터럴의 시작을 알리는 구문 규칙으로 사용되기도 한다.
각 언어는 히어 도큐먼트 또는 유사 기능을 구현하는 구체적인 문법과 기능(예: 변수 보간 지원 여부, 이스케이프 시퀀스 처리 방식, 종료 구분자 규칙 등)에서 차이를 보인다. 일부 언어는 파이썬의 삼중 따옴표 문자열이나 C#의 있는 그대로의 문자열 리터럴(verbatim string literal)처럼 다른 이름이나 구문으로 유사한 기능을 제공하기도 한다.
각 프로그래밍 언어 및 환경별 구체적인 구현 방식과 예시는 아래 하위 섹션에서 자세히 설명한다.
3. 1. Perl
Perl에서는 `<<` 연산자와 구분자(delimiter)를 사용하여 히어 도큐먼트를 정의한다.[8][17] 구분자를 어떤 종류의 따옴표로 묶는지에 따라 히어 도큐먼트 내부의 내용 처리 방식이 달라지는데, 이는 일반적인 문자열 리터럴 처리 방식과 유사하다.
히어 도큐먼트를 끝내는 종료 구분자는 반드시 해당 줄의 맨 앞에 위치해야 한다. 또한, 히어 도큐먼트의 내용은 시작 구분자가 선언된 줄의 다음 줄부터 시작된다.
다음은 큰따옴표를 사용하여 변수 보간이 이루어지는 예시이다.
```perl
my $sender = "Buffy the Vampire Slayer";
my $recipient = "Spike";
print <<"END";
Dear $recipient,
I wish you to leave Sunnydale and never return.
Not Quite Love,
$sender
END
```
위 코드의 출력은 다음과 같다.
```text
Dear Spike,
I wish you to leave Sunnydale and never return.
Not Quite Love,
Buffy the Vampire Slayer
```
다음은 작은따옴표를 사용하여 변수 보간을 막는 예시이다.
```perl
print <<'END';
Dear $recipient,
I wish you to leave Sunnydale and never return.
Not Quite Love,
$sender
END
```
위 코드의 출력은 다음과 같다. 변수명이 그대로 출력되는 것을 볼 수 있다.
```text
Dear $recipient,
I wish you to leave Sunnydale and never return.
Not Quite Love,
$sender
```
백틱을 사용하면 히어 도큐먼트의 내용이 셸 명령어로 실행된다. (이 기능은 실행 환경에 따라 동작이 다를 수 있다.)
```perl
my $shell_script_stdout = <<`END`;
echo foo
echo bar
END
# $shell_script_stdout 변수에는 "foo\nbar\n" 문자열이 저장된다.
```
한 줄에 여러 개의 히어 도큐먼트를 시작하는 것도 가능하다.
```perl
say(<
This is the beginning:
BEGIN
And now it is over!
END
# 위 코드는 아래와 동일하게 동작한다.
# say("This is the beginning:\nthis is the middle\nAnd now it is over!\n");
```
종료 구분자 자체에 공백을 포함시켜, 코드의 들여쓰기를 유지하면서 히어 도큐먼트를 사용할 수도 있다.
```perl
say <<' END';
Hello World
END
# 종료 구분자 ' END' 앞에는 공백 두 개가 있다.
```
Perl 버전 5.26부터는[9] 물결표시(`~`)를 구분자 앞에 붙여 히어 도큐먼트 내용의 들여쓰기를 자동으로 제거하는 기능이 추가되었다.
```perl
# 앞부분의 공백 없이 "Hello there\n"를 출력한다.
if (1) {
print <<~EOF;
Hello there
EOF
}
3. 2. PHP
PHP에서 히어 도큐먼트는 '''히어독'''(heredoc)이라고 불린다. 히어독은 `<<<` 연산자 뒤에 식별자를 붙여 시작하며, 해당 식별자만 있는 행으로 종료된다. 히어독 텍스트는 큰따옴표로 묶인 문자열과 거의 동일하게 동작하며, 변수를 확장할 수 있다. 예를 들어, `$`는 변수의 시작으로, `${` 또는 `{$`는 복잡한 변수의 시작으로 해석된다.
$name = "Joe Smith";
$occupation = "Programmer";
// 히어독 예제
echo <<
이것은 히어독 섹션입니다.
자세한 내용은 지역 $occupation 인 $name 에게 문의하세요.
감사합니다!
EOF;
// 히어독 내용을 변수에 할당하는 예제
$toprint = <<
안녕하세요 $name! 히어독 섹션을 변수에 할당할 수도 있습니다!
EOF;
echo $toprint;
?>
위 코드의 출력 결과는 다음과 같다.
```text
이것은 히어독 섹션입니다.
자세한 내용은 지역 Programmer 인 Joe Smith 에게 문의하세요.
감사합니다!
안녕하세요 Joe Smith! 히어독 섹션을 변수에 할당할 수도 있습니다!
```
PHP 7.3 이전 버전에서는 히어독을 닫는 식별자가 포함된 줄에는 선택적인 종료 세미콜론 외에 다른 문자가 포함될 수 없었다. 만약 다른 문자가 포함되면 닫는 식별자로 인식되지 않아 구문 분석 오류가 발생할 수 있었다.[10] 하지만 PHP 7.3 버전부터는 닫는 식별자 뒤에 세미콜론이나 줄 바꿈이 필수가 아니며, 닫는 식별자를 들여쓰는 것도 가능하다. 이 경우 들여쓴 만큼의 공백이 히어독 내용의 모든 줄 시작 부분에서 제거된다.[10]
PHP 5.3 버전부터는 식별자를 작은따옴표(`'`)로 묶어 변수 확장을 비활성화하는 '''나우독'''(nowdoc) 기능도 지원한다. 이는 Perl의 방식과 유사하다.[11][18]
// 나우독 예제
$sender = 'Buffy Summers';
$recipient = 'Spike';
$x = <<<'END'
Dear $recipient,
I wish you to leave Sunnydale and never return.
Not Quite Love,
$sender
END;
// $x 변수에는 아래 문자열이 그대로 저장됨:
// Dear $recipient,
//
// I wish you to leave Sunnydale and never return.
//
// Not Quite Love,
// $sender
?>
또한, PHP 5.3부터는 식별자를 큰따옴표(`"`)로 묶는 것도 가능하지만, 이는 식별자를 아무것도 묶지 않은 일반적인 히어독과 동일하게 동작한다.
3. 3. Ruby
루비에서도 히어 도큐먼트를 지원한다. 이는 `<<식별자`를 포함하는 행의 다음 행부터 `식별자`만 있는 행의 바로 앞까지를 문자열 리터럴로 취급하는 기능이다.[7][22]
다음은 루비에서 히어 도큐먼트를 사용하여 문자열을 만드는 기본적인 예시이다.
puts <
식료품 목록
1. 샐러드 믹스.
2. 딸기.*
3. 시리얼.
4. 우유.*
GROCERY_LIST
위 코드를 실행하면 다음과 같이 출력된다.
식료품 목록
1. 샐러드 믹스.
2. 딸기.*
3. 시리얼.
4. 우유.*
루비의 히어 도큐먼트는 기본적으로 큰따옴표 문자열처럼 처리되므로, `#{}` 구문을 사용하여 코드 보간(interpolation)이 가능하다. 또한, 시작 구분자를 `<<-식별자` 형태로 사용하면 종료 식별자 앞에 공백이나 탭 문자를 사용한 들여쓰기를 허용한다. 종료 식별자가 있는 줄에는 식별자 외에 다른 문자(주석 포함)가 없어야 한다.
now = Time.now
puts <<-EOF
지금 시각은 #{now.hour}시입니다.
종료 식별자 앞에는 공백이 올 수 있습니다.
EOF
루비 2.3 버전부터는 시작 구분자를 `<<~식별자` 형태로 사용하여 히어 도큐먼트 내용의 불필요한 선행 공백을 제거할 수 있다. 이 기능은 내용 전체에서 가장 적게 들여쓴 줄을 기준으로 해당 깊이만큼의 공백을 모든 줄의 시작 부분에서 제거한다. 들여쓰기 깊이를 계산할 때 공백이나 탭으로만 이루어진 줄은 무시된다.
# Ruby 2.3 이상
puts <<~EOF
이 줄은 두 칸 들여쓰기 되어 있습니다.
이 줄은 네 칸 들여쓰기 되어 있습니다.
이 줄은 여섯 칸 들여쓰기 되어 있습니다.
EOF
위 코드는 선행 공백이 제거되어 다음과 같이 출력된다.
이 줄은 두 칸 들여쓰기 되어 있습니다.
이 줄은 네 칸 들여쓰기 되어 있습니다.
이 줄은 여섯 칸 들여쓰기 되어 있습니다.
시작 식별자를 어떤 종류의 따옴표로 묶느냐에 따라 히어 도큐먼트의 처리 방식이 달라진다.
price = 1000
# 큰따옴표와 동일 (보간 O)
puts <
가격은 #{price}원입니다. \n 줄바꿈
EOS
# 작은따옴표 (보간 X, 이스케이프 X)
puts <<'EOS'
가격은 #{price}원입니다. \n 줄바꿈
EOS
# 백틱 (셸 명령어 실행)
puts <<`EOC`
echo "현재 디렉토리:"
pwd
EOC
루비에서는 히어 도큐먼트 자체가 하나의 식(expression)으로 취급되므로, 메서드 호출 시 인수로 직접 전달하거나 히어 도큐먼트를 수신자로 하여 메서드를 호출할 수도 있다.
# 메서드의 인수로 히어 도큐먼트 사용
def print_message(msg)
puts "메시지: #{msg}"
end
print_message(<
이것은
히어 도큐먼트로
만든 메시지입니다.
MESSAGE
# 히어 도큐먼트를 수신자로 하여 메서드 호출
puts <
이 내용은
대문자로
변환됩니다.
CONTENT
# 출력: 이 내용은\n대문자로\n변환됩니다.\n
또한, 한 줄에 여러 개의 히어 도큐먼트를 시작하여 연결할 수도 있다.
print <
첫 번째
히어 도큐먼트
FIRST
두 번째
히어 도큐먼트
SECOND
3. 4. Python
파이썬은 작은따옴표 세 개(`'''`) 또는 큰따옴표 세 개(`"""`)로 묶어 여러 줄 문자열 리터럴을 지원한다. 이러한 방식은 히어 도큐먼트와 유사하게 문자열 내의 줄 바꿈이나 공백 등을 그대로 유지한다.
print("""
Customer: Not much of a cheese shop is it?
Shopkeeper: Finest in the district , sir.
""")
파이썬 3.6 버전부터는 f-문자열(formatted string literal)을 사용하여 문자열 내에 변수나 표현식의 값을 쉽게 삽입할 수 있다.
shop_type = "CHEESE"
accolade = "finest"
print(f"""
Customer: Not much of a {shop_type.lower()} shop is it?
Shopkeeper: {accolade.capitalize()} in the district , sir.
""")
또는 문자열 객체의 `format()` 메서드를 사용하여 변수를 치환할 수도 있다.
message="""Dear {recipient},
I wish you to leave Sunnydale and never return.
Not Quite Love,
{sender}
"""
print(message.format(sender='Buffy the Vampire Slayer', recipient='Spike'))
파이썬 3.0 미만 버전에서는 `print`가 함수가 아닌 키워드였다. 또한, `string` 모듈의 `Template` 클래스[19]를 사용하여 변수 치환 기능을 구현할 수도 있다.
3. 5. C#
"); // ""는 " 하나로 처리됨
// 정규 표현식 패턴 작성 예시
System.Console.WriteLine(Regex.Match(path1, "^.+\\.(.+)$").Success); // 일반 문자열 패턴
System.Console.WriteLine(Regex.Match(path2, @"^.+\.(.+)$").Success); // 있는 그대로의 문자열 리터럴 패턴 (이스케이프 불필요)
3. 6. C++
C++11부터 C++는 사용자 지정 구분 기호를 사용하는 Raw 문자열 리터럴(Raw string literal) 기능을 지원한다. Raw 문자열 리터럴은 `R`을 접두사로 사용하며, 그 뒤에 `"식별자(`와 `)식별자"` 사이에 내용을 작성하는 형태이다. 여기서 식별자는 사용자가 임의로 지정할 수 있다.
#include
const char* str = R"my_delimiter(Start of string. New line
slash \ quote " ' parens ) ( End of string)my_delimiter";
// std::cout << str << std::endl; // 원본에는 출력 코드가 포함되어 있었으나, 리터럴 정의 예시에 집중
위 코드에서 `my_delimiter`가 사용자 지정 구분 기호이며, 이 구분 기호로 감싸인 부분은 Raw 문자열 리터럴이 된다. 이 문자열은 아래와 같이 해석된다. Raw 문자열 리터럴 내에서는 줄 바꿈이나 특수 문자(백슬래시 `\`, 따옴표 `" '` 등)가 보이는 그대로 문자열에 포함된다.
Start of string. New line
slash \ quote " ' parens ) ( End of string
Raw 문자열 리터럴의 식별자는 0자에서 최대 16자까지 가능하며, 공백 문자, 괄호 `()`, 백슬래시 `\`를 제외한 기본 소스 문자 집합의 모든 멤버를 사용할 수 있다.
Raw 문자열 리터럴의 가장 큰 특징 중 하나는 문자열 내부의 이스케이프 시퀀스가 처리되지 않는다는 점이다. 예를 들어 `\n`은 개행 문자로 해석되지 않고 문자 그대로 `\`와 `n`으로 인식된다.
// Raw 문자열 내의 이스케이프 시퀀스는 전개되지 않는다.
char const *a = R"('\n'이라는 이스케이프 시퀀스는 개행 문자를 나타낸다。)";
// 식별자를 사용하면 Raw 문자열 안에 유사한 표현을 넣을 수 있다.
wchar_t const *b = LR"...(Raw 문자열은 R"(...)"처럼 쓴다)...";
char16_t const *c = uR"xyz(
"\u20AC"와 같은 유니코드 문자를 나타내는 이스케이프 시퀀스도
Raw 문자열에서는 전개되지 않으므로 소스 코드의 인코딩으로 적절한 것을 선택하고
"€"와 같이 직접 쓰는 것 외에는 Raw 문자열에 넣는 방법이 없다.
)xyz";
위 예제처럼 `LR` (wchar_t), `uR` (char16_t), `UR` (char32_t) 접두사를 사용하여 다양한 문자 타입의 Raw 문자열 리터럴을 정의할 수도 있다. 유니코드 문자를 Raw 문자열에 직접 포함시키려면 소스 파일의 인코딩을 해당 문자를 지원하는 방식(예: UTF-8)으로 설정해야 한다.
3. 7. D
D 언어는 버전 2.0부터 'q' 접두 문자를 사용하여 히어 도큐먼트 스타일의 문자열을 지원한다.
식별자를 사용하는 방식은 `q"식별자`로 시작하며, 바로 다음 줄 바꿈 뒤부터 문자열 내용을 작성하고, 맨 마지막 줄의 시작 부분에 `식별자"`를 써서 문자열을 끝낸다. 여기서 '식별자'는 사용자가 임의로 정할 수 있다.
int main() {
string list = q"IDENT
1. Item One
2. Item Two
3. Item Three
IDENT";
writef( list );
}
또한 D 언어는 여러 종류의 따옴표 구분 기호를 사용하여 유사한 기능을 지원한다. 예를 들어, 문자열을 `q"[ ... ]"`와 같이 대괄호로 감싸거나, 소괄호 `()`, 꺾쇠괄호 `<>`, 중괄호 `{}` 등을 사용할 수도 있다.
int main() {
string list = q"[1. Item One
2. Item Two
3. Item Three]";
writef( list );
}
3. 8. R
R은 파일 리터럴을 가지고 있지 않지만, 문자열 리터럴과 문자열-파일 함수를 결합하여 히어 도큐먼트와 유사한 기능을 제공한다. R의 문자열 리터럴은 내부에 줄 바꿈을 포함한 임의의 공백 문자를 허용한다.
이렇게 작성된 여러 줄 문자열은 `textConnection()` 함수를 사용하여 파일 디스크립터처럼 다룰 수 있다. 즉, 문자열 데이터를 마치 파일에서 읽어오는 것처럼 처리할 수 있게 해준다. 예를 들어, 다음 코드는 소스 코드에 포함된 표 형식의 데이터를 데이터 프레임 변수로 읽어들이는 방법을 보여준다.
str <-
"State Population Income Illiteracy Life.Exp Murder HS.Grad Frost
Alabama 3615 3624 2.1 69.05 15.1 41.3 20
Alaska 365 6315 1.5 69.31 11.3 66.7 152
Arizona 2212 4530 1.8 70.55 7.8 58.1 15
Arkansas 2110 3378 1.9 70.66 10.1 39.9 65"
x <- read.table(textConnection(str), header=TRUE, row.names=1)
R에서는 일반적인 문자열 리터럴에 개행을 넣을 수 있지만, 다른 언어의 히어 도큐먼트 기능과 달리 문자열 내에서 변수 치환은 지원하지 않는다.
3. 9. Racket
Racket에서는 "히어 문자열"이라는 기능을 제공한다. 이는 #<<
로 시작하며, 그 뒤에 오는 문자열은 종료 구분자로 사용된다.[14][20] 문자열의 내용은 #<<
가 있는 줄 다음 줄부터 시작하여, 종료 구분자만 있는 줄 바로 앞 줄까지 포함된다. 즉, 종료 구분자 앞의 줄 바꿈 문자는 문자열에 포함되지 않는다.
다음은 Racket 히어 문자열의 간단한 예시이다.
```racket
#lang racket
(displayln
#<
Racket에 의한 히어 문자열의 샘플.
HERESTRING
)
```
히어 문자열 내부에서는 이스케이프 시퀀스가 처리되지 않는다. 모든 문자는 종료 구분자를 포함하여 문자열에 그대로 포함된다. 종료 구분자에는 유니코드 문자, 공백, 이모티콘 등도 사용할 수 있다.
```racket
#lang racket
(displayln
#<
이 문자열은 여러 줄로 이루어져 있으며,
또한 Unicode에 있는 어떤 문자도 사용할 수 있다.
€나 ☠, ♡에 ①라도 상관 없다.
이 다음 줄이 종료이지만, 종료 구분 기호에도 Unicode 문자라면 무엇이든 사용할 수 있다.
Racket의 히어 문자열 ☺
)
```
히어 문자열은 일반적인 문자열이 사용될 수 있는 대부분의 상황에서 사용할 수 있다. 예를 들어, `printf` 함수와 함께 사용할 수 있다.
```racket
#lang racket
(printf #<
Dear ~a,
Thanks for the insightful conversation ~a.
~a
END
"Isaac"
"yesterday"
"Carl")
```
Racket의 언어 확장인 at-exp
를 사용하면 @-표현식이라는 대안적인 방법을 사용할 수 있다.[15][21] 이는 문자열뿐만 아니라 언어의 다른 부분과 함께 구성될 수 있는 구문 형식이다.
```racket
#lang at-exp racket
(displayln @string-append{
This is a long string,
very convenient when a
long chunk of text is
needed.
No worries about escaping
"quotes" or \escapes. It's
also okay to have λ, γ, θ, ...
Embed code: @(number->string (+ 3 4))
})
3. 10. Windows PowerShell
PowerShell에서 히어 도큐먼트는 '''히어 문자열'''(here-string)로 지칭된다. 히어 문자열은 시작 구분자(@"
또는 @'
)로 시작하여 자체적으로 한 줄에 종료 구분자("@
또는 '@
)로 끝나며, 문자열을 종료한다. 시작 구분자와 종료 구분자 사이의 모든 문자는 문자열 리터럴로 간주된다.
큰따옴표가 있는 히어 문자열(@"..."@
)을 사용하면 변수를 해석할 수 있지만, 작은따옴표(@'...'@
)를 사용하면 해석되지 않는다.
변수 보간은 단순 변수(예: $x
)나 $()
안에 문장 집합을 넣어 실행할 때(예: $($x.y)
또는 $(Get-Process | Out-String)
) 적용된다.
다음 PowerShell 코드에서는 텍스트가 히어 문자열을 사용하여 함수에 전달된다.ConvertTo-UpperCase
함수는 다음과 같이 정의된다.
PS > function ConvertTo-UpperCase($string) { $string.ToUpper() }
PS > ConvertTo-UpperCase @'
>> one two three
>> eins zwei drei
>> '@
ONE TWO THREE
EINS ZWEI DREI
다음은 큰따옴표가 있는 히어 문자열을 사용하여 변수 보간 및 문장 실행을 보여주는 예이다.
PS > $doc, $marty = 'Dr. Emmett Brown', 'Marty McFly'
PS > $time = [DateTime]'Friday, October 25, 1985 8:00:00 AM'
PS > $diff = New-TimeSpan -Minutes 25
PS > @"
>> $doc : Are those my clocks I hear?
>> $marty : Yeah! Uh, it's $($time.Hour) o'clock!
>> $doc : Perfect! My experiment worked! They're all exactly $($diff.Minutes) minutes slow.
>> $marty : Wait a minute. Wait a minute. Doc... Are you telling me that it's $(($time + $diff).ToShortTimeString())?
>> $doc : Precisely.
>> $marty : Damn! I'm late for school!
>> "@
Dr. Emmett Brown : Are those my clocks I hear?
Marty McFly : Yeah! Uh, it's 8 o'clock!
Dr. Emmett Brown : Perfect! My experiment worked! They're all exactly 25 minutes slow.
Marty McFly : Wait a minute. Wait a minute. Doc... Are you telling me that it's 08:25?
Dr. Emmett Brown : Precisely.
Marty McFly : Damn! I'm late for school!
작은따옴표가 있는 히어 문자열을 사용하면 변수 보간이 일어나지 않아 출력은 다음과 같다.
PS > @'
>> $doc : Are those my clocks I hear?
>> $marty : Yeah! Uh, it's $($time.Hour) o'clock!
>> $doc : Perfect! My experiment worked! They're all exactly $($diff.Minutes) minutes slow.
>> $marty : Wait a minute. Wait a minute. Doc... Are you telling me that it's $(($time + $diff).ToShortTimeString())?
>> $doc : Precisely.
>> $marty : Damn! I'm late for school!
>> '@
$doc : Are those my clocks I hear?
$marty : Yeah! Uh, it's $($time.Hour) o'clock!
$doc : Perfect! My experiment worked! They're all exactly $($diff.Minutes) minutes slow.
$marty : Wait a minute. Wait a minute. Doc... Are you telling me that it's $(($time + $diff).ToShortTimeString())?
$doc : Precisely.
$marty : Damn! I'm late for school!
3. 11. 기타 언어 및 환경
Lua에서는 문자열을 ''''와 '' ''로 묶어 여러 줄에 걸친 문자열 리터럴로 사용할 수 있다. 이 방식은 줄 바꿈을 그대로 유지하며, 이스케이프 문자를 해석하지 않는다. 문자열 내부에 '' ]] ''를 포함해야 할 경우를 대비해, Lua 5.1부터는 시작 대괄호 사이에 여러 개의 등호(=
)를 넣고, 같은 개수의 등호를 가진 닫는 대괄호(]
)로 문자열을 끝내는 구문이 도입되었다.
local ls =
첫 번째 줄 바꿈은 문자열의 일부가 되지 않는다.
즉, 이 문자열은 2행이다.]]
local lls = [==[
이 표기법은 Windows의 경로를 표현하는 경우에도 편리하다.
local path = [=[C:\Windows\Fonts]=]
]==]
YAML은 들여쓰기를 사용하여 구조를 표현하며, 구분자 충돌 문제없이 여러 줄 문자열을 나타내기 위해 접힌 스타일(>
)이나 리터럴 스타일(|
)을 사용한다.
```yaml
caption: "YAML을 사용한 히어 도큐먼트 스타일 기능의 예시"
date: "2007-06-01"
example: >
HTML은 수정 없이 YAML에 들어갑니다.
message: |
심지어 큰 값의 이에도"
```
Tcl은 일반 문자열 리터럴 안에 줄 바꿈 문자를 직접 포함할 수 있어 히어 도큐먼트를 위한 별도의 문법은 없다. 중괄호({}
)로 묶인 문자열은 변수 치환이나 명령 치환 없이 그대로 사용되며, 큰따옴표(""
)로 묶인 문자열은 변수와 명령 치환이 이루어진다.
```tcl
# 중괄호 사용 예시 (변수 치환 없음)
puts {
Grocery list
1. Salad mix.
2. Strawberries.*
3. Cereal.
4. Milk.*
}
# 큰따옴표 사용 예시 (변수 치환 있음)
set sender "Buffy the Vampire Slayer"
set recipient "Spike"
puts "
Dear $recipient,
I wish you to leave Sunnydale and never return.
Not Quite Love,
$sender
"
# 문자열 앞뒤의 불필요한 줄 바꿈 제거
puts [string trim "
Dear $recipient,
I wish you to leave Sunnydale and never return.
Not Quite Love,
$sender
" \n]
```
DCL 스크립트에서는 달러 기호($
)로 시작하지 않는 모든 줄이 암묵적으로 이전 명령의 입력으로 취급된다. 이는 히어 도큐먼트와 유사하게 작동하며, 이 입력은 프로그램으로 전달되거나 논리적 이름 ''SYS$INPUT'' (유닉스의 stdin과 유사)을 통해 명시적으로 참조될 수 있다.
```console
$ TYPE SYS$INPUT
이 텍스트는 TYPE 명령에 의해 화면에 직접 에코됩니다.
$! 다른 명령 ...
```
출력:
```output
이 텍스트는 TYPE 명령에 의해 화면에 직접 에코됩니다.
```
또한, ''DECK'' 명령어를 사용하여 명시적으로 입력 데이터를 제공할 수 있으며, 이 데이터는 ''$ EOD'' 명령이나 ''DECK'' 명령어의 ''/DOLLARS'' 매개변수로 지정된 문자열 패턴이 나올 때까지 계속된다.[16]
```text
$ RUN ADD_SUMS.EXE
$ DECK
$13.53
$3.33
$2.33
$ EOD
```
IBM의 z/OS 등에서 사용되는 JCL에서는 ''DD *'' 문을 사용하여 작업 스트림 내에 데이터를 직접 포함시킬 수 있다. 데이터는 다음 JCL 문(//
로 시작)이나 기본 종료 구분자인 ''/*''가 나올 때까지 계속된다. 특정 구분자를 사용하고 싶다면 ''DD *,DLM=구분자'' 형식을 사용한다.
//SYSIN DD *
APROG START
XR 15,15
BR 14
END
/*
마이크로소프트 NMAKE 유틸리티는 인라인 파일(inline file)이라는 유사한 기능을 제공한다.[23] 인라인 파일은 ''<<'' (임시 파일 생성) 또는 ''<<경로이름'' (지정된 파일 생성 또는 덮어쓰기)으로 시작한다. 종료는 ''<<''만 있는 줄로 이루어지며, 선택적으로 ''KEEP'' 또는 ''NOKEEP'' 키워드를 뒤에 붙여 파일 보존 여부를 지정할 수 있다.
```make
target0: dependent0
command0 <<
임시 인라인 파일
...
<<
target1: dependent1
command1 <<
임시, 하지만 보존된 인라인 파일
...
<
target2: dependent2
command2 <
이름이 지정되었지만 삭제된 인라인 파일
...
<
target3: dependent3
command3 <
이름이 지정된 인라인 파일
...
<
```
Data URI scheme은 대부분의 주요 웹 브라우저에서 지원되며, ''data:''로 시작하는 URI를 사용하여 문서 내에 다른 데이터를 직접 포함시키는 방식으로, 히어 도큐먼트와 유사하게 활용될 수 있다.
4. 한국 개발 환경에서의 활용
한국의 개발 환경에서도 히어 도큐먼트는 다양한 분야에서 유용하게 활용된다. 특히 셸 스크립트 작성 시 여러 줄의 명령어 목록이나 설정 내용을 코드 안에 직접 넣을 때 자주 사용된다. 예를 들어, 복잡한 SQL 질의어나 HTML 코드 조각, 설정 파일 내용 등을 스크립트 내에 깔끔하게 포함시킬 수 있다.
또한, 앤서블(Ansible)이나 테라폼(Terraform)과 같은 자동화 도구에서도 히어 도큐먼트를 활용하여 설정 파일이나 스크립트 일부를 동적으로 생성하거나 전달하는 데 사용된다. 이를 통해 코드를 읽기 쉽게 만들고, 별도의 설정 파일을 관리해야 하는 번거로움을 줄여 생산성을 높이는 데 기여한다. 즉, 코드 내에 필요한 텍스트 블록을 직접 포함함으로써 외부 파일에 대한 의존성을 낮추고 코드의 이해도를 높이는 장점이 있다.
참조
[1]
웹사이트
Shell Here Document Overview
http://content.hccfl[...]
hccfl.edu
2014-05-28
[2]
웹사이트
Here-Document description in the POSIX/SUS standard
http://pubs.opengrou[...]
2018-04-20
[3]
문서
3.6.6 Here Documents
https://www.gnu.org/[...]
[4]
문서
Using variables inside a bash heredoc
https://stackoverflo[...]
[5]
웹사이트
Darwin tcsh man page
https://developer.ap[...]
2018-04-20
[6]
웹사이트
perldata: Special Literals
http://perldoc.perl.[...]
2013-08-31
[7]
Webarchive
Ruby: Object: __END__
http://ruby-doc.org/[...]
2017-07-11
[8]
웹사이트
Perl operators and precedence
http://perldoc.perl.[...]
2010-05-22
[9]
웹사이트
Perl5260delta - what is new for perl v5.26.0 - Perldoc Browser
https://perldoc.perl[...]
2018-12-21
[10]
웹사이트
Heredoc in PHP manual
http://php.net/hered[...]
2011-04-06
[11]
웹사이트
PHP: Strings - Manual
http://www.php.net/m[...]
2011-09-07
[12]
웹사이트
JEP 378: Text Blocks
https://openjdk.org/[...]
2024-06-05
[13]
웹사이트
Text Blocks (JEP 378) - javaalmanac.io
https://javaalmanac.[...]
2024-06-05
[14]
웹사이트
Here string in Racket Documentation
http://docs.racket-l[...]
2011-09-17
[15]
웹사이트
"@ Syntax in Racket Documentation"
http://docs.racket-l[...]
2011-09-17
[16]
웹사이트
HP OpenVMS DCL Dictionary
http://h71000.www7.h[...]
2015-04-21
[17]
문서
Perl operators and precedence
http://perldoc.perl.[...]
[18]
문서
文字列
http://www.php.net/m[...]
[19]
문서
PEP 292 (Simpler String Substitutions)
http://www.python.or[...]
[20]
문서
Here string in Racket Documentation
http://docs.racket-l[...]
[21]
문서
"@ Syntax in Racket Documentation"
http://docs.racket-l[...]
[22]
문서
ヒアドキュメント (行指向文字列リテラル)
https://docs.ruby-la[...]
2019-01-09
[23]
문서
メイクファイルのインライン ファイル
http://msdn.microsof[...]
Microsoft Developer Network
2013-07-24
[24]
웹인용
Here document - Rosetta Code
http://rosettacode.o[...]
2017-02-20
[25]
웹인용
Darwin tcsh man page
https://developer.ap[...]
2019-08-31
[26]
웹인용
Shell Here Document Overview
http://content.hccfl[...]
hccfl.edu
2014-05-28
[27]
웹인용
Here-Document description in the POSIX/SUS standard
http://pubs.opengrou[...]
2019-08-31
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com