[linux] bash에서“cat << EOF”는 어떻게 작동합니까?

프로그램에 여러 줄 입력을 입력하는 스크립트를 작성해야했습니다 ( psql).

약간의 인터넷 검색 결과 다음과 같은 구문이 작동합니다.

cat << EOF | psql ---params
BEGIN;

`pg_dump ----something`

update table .... statement ...;

END;
EOF

이렇게하면 여러 줄 문자열 (에서 BEGIN;까지 END;포함) 을 올바르게 구성하고 에 입력으로 파이프합니다 psql.

그러나 어떻게 / 왜 작동하는지 잘 모르겠습니다. 어떻게 설명 할 수 있습니까?

나는 주로 말하는 겁니다 cat << EOF, 내가 알고 >, 파일로 출력하는 >>파일에 추가, <파일에서 입력을 읽습니다.

<<정확히 무엇을 합니까?

그리고 그것에 대한 맨 페이지가 있습니까?



답변

이것을 stdin에 문자열을 제공하기 위해 heredoc 형식 이라고 합니다 . 자세한 내용은 https://en.wikipedia.org/wiki/Here_document#Unix_shells 를 참조하십시오.


보낸 사람 man bash:

여기에 문서

이 유형의 방향 재 지정은 단어 만 포함하는 행 (후행 공백 없음)이 표시 될 때까지 쉘이 현재 소스에서 입력을 읽도록 지시합니다.

해당 지점까지 읽은 모든 라인은 명령의 표준 입력으로 사용됩니다.

여기 문서의 형식은 다음과 같습니다.

          <<[-]word
                  here-document
          delimiter

word 에서 매개 변수 확장, 명령 대체, 산술 확장 또는 경로 이름 확장이 수행되지 않습니다
. 단어의 문자 가 따옴표로 묶이면
구분 기호word 에서 따옴표를 제거한 결과이며 여기 문서 의 줄은 확장되지 않습니다. 단어 를 인용 부호로 묶지 않으면 여기 문서 의 모든 줄에
매개 변수 확장, 명령 대체 및 산술 확장이 적용됩니다. 후자의 경우, 문자 순서는 \<newline>무시되고, \문자를 인용하는 데 사용해야합니다 \, $하고 `.

재 지정 연산자가 있으면 <<-모든 선행 탭 문자가 입력 행과 구분 기호를 포함하는 행에서 제거됩니다 . 이를 통해 쉘 스크립트 내의 문서를 자연스럽게 들여 쓸 수 있습니다.


답변

cat <<EOF구문은 Bash에서 여러 줄 텍스트로 작업 할 때 매우 유용합니다. 쉘 변수, 파일 또는 파이프에 여러 줄 문자열을 지정할 때

cat <<EOFBash 의 구문 사용법 예 :

1. 쉘 변수에 여러 줄 문자열 할당

$ sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)

$sql변수는 이제 너무 개행 문자를 보유하고 있습니다. 로 확인할 수 있습니다 echo -e "$sql".

2. Bash의 파일에 여러 줄 문자열을 전달하십시오.

$ cat <<EOF > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
EOF

print.sh파일은 이제 포함

#!/bin/bash
echo $PWD
echo /home/user

3. Bash의 파이프에 여러 줄 문자열을 전달하십시오.

$ cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF

b.txt파일을 포함 bar하고 baz라인. 같은 출력이로 인쇄됩니다 stdout.


답변

귀하의 경우 “EOF”를 “여기 태그”라고합니다. 기본적으로 <<Here쉘에게 “tag”까지 여러 줄 문자열을 입력 할 것임을 알려줍니다 Here. 당신이 원하는대로 당신은 종종있어,이 태그의 이름을 지정할 수 있습니다 EOF또는 STOP.

Here 태그에 대한 몇 가지 규칙 :

  1. 태그는 문자열, 대문자 또는 소문자 일 수 있지만 대부분의 사람들은 규칙에 따라 대문자를 사용합니다.
  2. 해당 줄에 다른 단어가 있으면 태그는 Here 태그로 간주되지 않습니다. 이 경우 문자열의 일부로 간주됩니다. 태그는 별도의 줄에 있어야하며 태그로 간주해야합니다.
  3. 태그는 해당 줄에 태그로 간주되는 선행 또는 후행 공백이 없어야합니다. 그렇지 않으면 문자열의 일부로 간주됩니다.

예:

$ cat >> test <<HERE
> Hello world HERE <-- Not by itself on a separate line -> not considered end of string
> This is a test
>  HERE <-- Leading space, so not considered end of string
> and a new line
> HERE <-- Now we have the end of the string


답변

POSIX 7

kennytm이 인용 man bash했지만 대부분 POSIX 7입니다. http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04 :

경로 재 지정 연산자 “<<“및 “<<-“는 모두 “여기 문서”라고하는 쉘 입력 파일에 포함 된 행을 명령 입력으로 경로 재 지정할 수 있습니다.

이 문서는 다음 단어 이후에 시작하여 사이에 문자가없는 구분 기호와 a 만 포함 된 줄이있을 때까지 계속되는 단일 단어로 취급됩니다. 그런 다음 다음 문서가 있으면 시작합니다. 형식은 다음과 같습니다.

[n]<<word
    here-document
delimiter

여기서 선택적 n은 파일 설명자 번호를 나타냅니다. 숫자를 생략하면 여기 문서는 표준 입력 (파일 설명자 0)을 나타냅니다.

단어의 문자가 따옴표로 묶인 경우 단어에서 따옴표 제거를 수행하여 구분 기호를 구성해야하며 여기에 문서 행을 확장하지 않아야합니다. 그렇지 않으면 구분자가 단어 자체가됩니다.

단어의 문자가 인용되지 않으면, 본 문서의 모든 줄은 매개 변수 확장, 명령 대체 및 산술 확장을 위해 확장되어야합니다. 이 경우 입력의 in은 내부 큰 따옴표로 작동합니다 (큰 따옴표 참조). 그러나 큰 따옴표 문자 ( ‘ “‘)는 큰 따옴표가”$ () “,”“ “또는”$ {} “내에있는 경우를 제외하고는 여기에서 특별히 다루지 않습니다.

방향 재 지정 기호가 “<<-“이면 모든 선행 <tab>문자는 입력 행과 후행 구분 기호를 포함하는 행에서 제거됩니다. 한 줄에 둘 이상의 “<<“또는 “<<-“연산자가 지정된 경우 첫 번째 연산자와 관련된 여기 문서는 응용 프로그램에서 먼저 제공해야하며 셸에서 먼저 읽습니다.

여기서 터미널 문서에서이 문서를 읽고 셸이 대화 형인 경우 셸 변수에 설명 된대로 처리 된 변수 PS2의 내용을 구분자가 인식 될 때까지 각 입력 줄을 읽기 전에 표준 오류에 기록해야합니다.

아직 제시되지 않은 몇 가지 예.

따옴표는 매개 변수 확장을 방지합니다

인용없이:

a=0
cat <<EOF
$a
EOF

산출:

0

따옴표로 :

a=0
cat <<'EOF'
$a
EOF

또는 (추악하지만 유효한) :

a=0
cat <<E"O"F
$a
EOF

출력 :

$a

하이픈은 선행 탭을 제거합니다

하이픈없이 :

cat <<EOF
<tab>a
EOF

<tab>리터럴 탭은 어디에 있고Ctrl + V <tab>

산출:

<tab>a

하이픈으로 :

cat <<-EOF
<tab>a
<tab>EOF

산출:

a

이것은 물론 cat주변 코드처럼 들여 쓰기 가 가능하여 읽기 쉽고 유지 관리가 쉽습니다. 예 :

if true; then
    cat <<-EOF
    a
    EOF
fi

불행히도 이것은 공백 문자에는 작동하지 않습니다. POSIX는 tab들여 쓰기를 선호 했습니다. Yikes.


답변

고양이 대신 티를 사용

원래 질문에 대한 대답은 아니지만 어쨌든 이것을 공유하고 싶었습니다. 루트 권한이 필요한 디렉토리에 구성 파일을 만들어야했습니다.

이 경우 다음이 작동하지 않습니다.

$ sudo cat <<EOF >/etc/somedir/foo.conf
# my config file
foo=bar
EOF

리디렉션은 sudo 컨텍스트 외부에서 처리되기 때문입니다.

나는 이것을 대신 사용했다 :

$ sudo tee <<EOF /etc/somedir/foo.conf >/dev/null
# my config file
foo=bar
EOF


답변

위의 답변에 대한 약간의 확장. 후행 >은 입력을 파일로 보내서 기존 컨텐츠를 겹쳐 씁니다. 그러나 특히 편리한 사용 방법은 다음 >>과 같이 파일 끝에 새 내용을 추가 하는 이중 화살표 입니다.

cat <<EOF >> /etc/fstab
data_server:/var/sharedServer/authority/cert /var/sharedFolder/sometin/authority/cert nfs
data_server:/var/sharedServer/cert   /var/sharedFolder/sometin/vsdc/cert nfs
EOF

이를 통해 fstab실수로 내용을 수정하는 것에 대해 걱정할 필요가 없습니다.


답변

이것은 반드시 원래 질문에 대한 대답은 아니지만 내 자신의 테스트 결과를 공유합니다. 이:

<<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test

다음과 같은 파일을 생성합니다 :

cat <<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test

따라서 cat 명령을 사용하는 것이 중요하지 않습니다.