코드가 포함 된 파일을 << EOF >> 분류하는 방법은 무엇입니까?


102

다음을 사용하여 코드를 파일로 인쇄하고 싶습니다 cat <<EOF >>.

cat <<EOF >> brightup.sh
!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
   curr=$((curr+406));
   echo $curr  > /sys/class/backlight/intel_backlight/brightness;
fi
EOF

하지만 파일 출력을 확인하면 다음과 같이 표시됩니다.

!/bin/bash
curr=1634
if [  -lt 4477 ]; then
   curr=406;
   echo   > /sys/class/backlight/intel_backlight/brightness;
fi

나는 작은 따옴표를 넣어 보았지만 출력에는 작은 따옴표도 포함되어 있습니다. 이 문제를 어떻게 피할 수 있습니까?


2
shebang도 수정해야합니다. 첫 번째 줄은 문자 그대로 있어야하며 #!/bin/bash다른 것은 #!없어야합니다. 바로 이것이 유효한 shebang 줄로 만들고 그 뒤에 오는 것은 인터프리터로가는 경로입니다.
tripleee 2015 년

1
을 참조 man bash하고을 검색 하십시오 Here Documents. 거기에 모든 세부 사항.
Hong

1
늦게는 프로세스 대체에 대한 현대적인 구문 $(command)`command`. 파일의 내용을 얻기 위해, 배쉬는이$(<file)
tripleee

답변:


160

최소한의 변경 만 필요합니다. 여기서 문서 구분 기호를 작은 따옴표로 묶으십시오 <<.

cat <<'EOF' >> brightup.sh

또는 동등하게 백 슬래시 이스케이프 :

cat <<\EOF >>brightup.sh

인용하지 않으면 here 문서는 변수 대체를 거치고 백틱이 평가됩니다.

전부가 아닌 일부 값을 확장해야하는 경우 방지하려는 값을 개별적으로 이스케이프해야합니다.

cat <<EOF >>brightup.sh
#!/bin/sh
# Created on $(date # : <<-- this will be evaluated before cat;)
echo "\$HOME will not be evaluated because it is backslash-escaped"
EOF

생산할 것이다

#!/bin/sh
# Created on Fri Feb 16 11:00:18 UTC 2018
echo "$HOME will not be evaluated because it is backslash-escaped"

@fedorqui가 제안한대로 다음은 관련 섹션입니다 man bash.

여기 문서

이러한 유형의 재 지정은 구분 기호 만 포함 된 행 (후행 공백 없음)이 표시 될 때까지 현재 소스에서 입력을 읽도록 쉘에 지시합니다. 그 지점까지 읽은 모든 행은 명령의 표준 입력으로 사용됩니다.

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

      <<[-]word
              here-document
      delimiter

매개 변수 확장, 명령 대체, 산술 확장 또는 경로 이름 확장은 단어에서 수행되지 않습니다. 단어의 문자가 인용 된 경우 구분 기호는 단어에서 인용 부호를 제거한 결과이며 여기 문서의 행은 확장되지 않습니다. 단어가 인용되지 않으면 here-document의 모든 행은 매개 변수 확장, 명령 대체 및 산술 확장의 대상이 됩니다. 후자의 경우 문자 시퀀스 \는 무시되며 \, $ 및`문자를 인용하는 데 \를 사용해야합니다.


1
heredoc 확장 변수를 피하는 방법을 표시 했습니까? 이것의 복제본으로. 이의가 없습니다. 제가했던 것처럼 Bash 문서 참조를 포함한다는 것뿐입니다 (단지 13,000 회 방문이 거의 100 회에 달하므로 매우 도움이되는 것 같습니다).
fedorqui은 'SO 해치지 중지'

@fedorqui이 ​​질문에 대한 답을 실제로 이식하고 싶습니까? 또는 중복 표시를 다른 방향으로 전환 할 수 있습니다. 답이 많이 나오지 않고 그냥 질문 점수 만 보았습니다.
tripleee

Mmm 그것들을 병합 하는 것은 어떨까요?이 질문을 대상 질문으로 삼으세요? 중복 질문은 제목이 좋지만 너무 길다는 것입니다. 그러나 늦게까지 꽤 많은 관심을 받았습니다 (한 달에 몇 가지 upvotes를 받고 있습니다 ).
fedorqui 'SO stop harming'6

@fedorqui 나는 병합의 개념을 좋아하지만 실제로 그것이 일어나는 것을 본 적이 없습니다. 내가 상황을 올바르게 이해한다면, 번거 로움과 복잡성이 이점보다 훨씬 크기 때문에 모드는 간단하지 않은 병합을 처리 할 수 ​​없습니다. 내가 한두 번 한 일은 유용하고 찬성 된 답변을 삭제하고 다른 질문으로 다시 게시하는 것이지만이 해결 방법을 거의 권장하지 않습니다.
tripleee

언제 할 가치가 있는지 말하기는 어렵습니다. 나는 좋은 질문이 게시되었을 때 이전에 다른 좋은 질문이 있다는 것을 알지 못하고 모두 좋은 답변을 가지고있는 사이트에서 그것을했습니다. 내 90 점 이상의 답변을 제거하는 것은 그 질문을 고아로 남겨 둘 것이기 때문에 좋은 계획이 아닌 것 같습니다.
fedorqui 'SO stop harming'6

20

또는 EOF 마커를 사용하여 확장이 수행되지 않도록 초기 마커를 인용해야합니다.

#-----v---v------
cat <<'EOF' >> brightup.sh
#!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
   curr=$((curr+406));
   echo $curr  > /sys/class/backlight/intel_backlight/brightness;
fi
EOF

IHTH


1
나는 당신의 게시물을 편집 할 것이지만 안전을 위해 그것은 #! / bin / bash가 아니라! / bin / bash가 아니어야 하는가?
Matthew Hoggan 2015

@MatthewHoggan : 네, 맞아요! 잡아 주셔서 감사합니다. 나는 지금 그것을 고치고있다.
셸터

16

이것은 작동해야합니다. 방금 테스트했고 예상대로 작동했습니다. 확장, 대체 또는 수행 한 작업이 없습니다.

cat <<< '
#!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
  curr=$((curr+406));
  echo $curr  > /sys/class/backlight/intel_backlight/brightness;
fi' > file # use overwrite mode so that you don't keep on appending the same script to that file over and over again, unless that's what you want. 

다음을 사용하는 것도 작동합니다.

cat <<< ' > file
 ... code ...'

또한, << EOF대체 및 변수 확장 등과 같은 heredocs를 사용할 때 발생한다는 점에 주목할 가치가 있습니다. 그래서 다음과 같이합니다.

cat << EOF > file
cd "$HOME"
echo "$PWD" # echo the current path
EOF

항상 변수 $HOME$PWD. 따라서 홈 디렉토리가 /home/foobar이고 현재 경로가 /home/foobar/bin이면 file다음과 같습니다.

cd "/home/foobar"
echo "/home/foobar/bin"

예상 대신 :

cd "$HOME"
echo "$PWD"

2
작은 따옴표로 묶인 here 문자열은 분명히 작은 따옴표를 포함 할 수 없으며 이는 금지 된 문제 일 수 있습니다. 여기 문서는 작은 따옴표와 큰 따옴표를 모두 포함해야하는 스크립트가있는 경우 유일하게 올바른 해결 방법입니다. 물론 OP의 간단한 예제에서는 그렇지 않습니다. 또한 접선 적으로 here-strings <<<는 Bash 3부터 만 사용할 수 있으며 다른 셸로 이식 할 수 없습니다.
트리플 리

<<<zsh을 형태로도 주문 가능합니다
알렉세이 마구 라

3
오늘 저는 heredoc의 시작 바로 뒤에 파일 이름을 가질 수 있다는 것을 배웠습니다. 감사합니다 @AlexejMagura!
chaseadamsio

0

나는 이것이 2 년 된 질문이라는 것을 알고 있지만 이것은 '방법'을 검색하는 사람들을위한 빠른 대답입니다.

어떤 것에도 따옴표를 붙이고 싶지 않다면 파일에 텍스트 블록을 작성하고 텍스트로 내보낼 변수 (예 : 스크립트에서 사용)를 이스케이프하고 원하는 변수를 이스케이프하지 마십시오. 변수 값으로 내 보냅니다.

#!/bin/bash

FILE_NAME="test.txt"
VAR_EXAMPLE="\"string\""

cat > ${FILE_NAME} << EOF
\${VAR_EXAMPLE}=${VAR_EXAMPLE} in ${FILE_NAME}  
EOF

"$ {VAR_EXAMPLE} ="string "in test.txt"를 test.txt에 기록합니다.

파일 이름을 생략하여 동일한 규칙으로 콘솔에 텍스트 블록을 출력하는데도 사용할 수 있습니다.

#!/bin/bash

VAR_EXAMPLE="\"string\""

cat << EOF
\${VAR_EXAMPLE}=${VAR_EXAMPLE} to console 
EOF

콘솔에 "$ {VAR_EXAMPLE} ="string "to console"을 출력합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.