연속 문자 뒤에 주석이 있는 bash 여러 줄 명령

연속 문자 뒤에 주석이 있는 bash 여러 줄 명령

고려하다

echo \ # this is a comment
foo

이는 다음을 제공합니다:

$ sh foo.sh
 # this is a comment
foo.sh: line 2: foo: command not found

몇번의 온라인 검색 끝에 한 곳을 발견했습니다.디지털로스 솔루션자매 사이트 Stack Overflow에서. 그래서 사람은 할 수 있습니다

echo `: this is a comment` \
foo

또는 대안적으로

echo $(: this is a comment) \
foo

그러나 DigitalRoss는 이러한 솔루션이 작동하는 이유를 설명하지 않습니다. 설명을 듣고 싶습니다. 그는 그 댓글에 이렇게 답했습니다.

goto아래와 같이 지정된 레이블로 분기하는 쉘 명령이 있었습니다 :. 사라졌지 goto만 여전히 : whatever구문을 사용할 수 있습니다... :이제 구문 분석된 주석입니다.

하지만 이식성에 대한 논의를 포함하여 더 자세한 내용과 맥락을 알고 싶습니다.

물론 다른 솔루션이 있는 사람도 있으면 좋을 것입니다.

이전 질문도 참조하세요쉘 스크립트에서 여러 줄 명령을 주석 처리하는 방법은 무엇입니까?.


아래 토론에서 중요한 정보를 얻으십시오. 이것은 `: this is a comment`단지 명령 대체입니다. 출력은 : this is a comment아무것도 아니며 배치된 위치에 있습니다 `: this is a comment`.

더 나은 옵션은 다음과 같습니다.

echo `# this is a comment` \
foo

답변1

주석은 첫 번째 개행 문자로 끝납니다(참조쉘 토큰 인식 규칙 10), 허용되지 않는 경우연속선이므로 이 코드는 foo별도의 명령줄에 있습니다.

echo # this is a comment \
foo

첫 번째 제안에서는 백슬래시 뒤에 개행 문자가 없으며 단지 공백을 인용하는 것입니다.

echo ' # this is a comment'
foo

$(: this is a comment)명령의 출력을 바꾸십시오 : this is a comment. 이 명령의 출력이 비어 있는 경우 실제로 줄 중간에 주석을 삽입하는 것은 매우 혼란스러운 방법입니다.

마법 같은 일은 일어나지 않습니다. :이는 일반적인 명령일 뿐입니다.콜론아무것도 하지 않는 유틸리티. 콜론 유틸리티는 쉘 구문에 명령이 필요하지만 다른 할 일이 없을 때 가장 유용합니다.

# Sample code to compress files that don't look compressed
case "$1" in
  *.gz|*.tgz|*.bz2|*.zip|*.jar|*.od?)
    :  # do nothing, the file is already compressed
    ;;
  *)
    bzip2 -9 "$1"
    ;;
esac

또 다른 사용 사례는 변수가 아직 설정되지 않은 경우 변수를 설정하는 관용구입니다.

: "${foo:=default value}"

goto에 대한 의견은 역사적입니다. 콜론 유틸리티는 심지어본 쉘,까지톰슨 쉘, 그것 중 하나가다지침. 콜론은 레이블을 의미합니다. 콜론은 goto 레이블에 대한 매우 일반적인 구문입니다(아직도 존재합니다).sed).

답변2

Bash 배열을 사용하여 이 작업을 수행할 수 있습니다.

#!/bin/bash
CMD=(
  echo  # this is a comment
  foo
  )

"${CMD[@]}"

이는 배열을 정의한 $CMD다음 확장합니다. 확장되면 결과 행이 평가되어 echo foo이 경우 실행됩니다.

(와 사이의 텍스트는 )배열을 정의하고 일반적인 bash 구문을 따르므로 다음 줄의 모든 내용은 #무시됩니다.

명령 및 매개변수 유지에 대한 참고 사항

${CMD[@]}공백이나 와일드카드 구두점과 같이 셸에서 해석될 각 요소의 문자를 유지하지 않고 배열 요소를 확장합니다. 확장되면 Bash는 발견된 모든 토큰을 일반적인 방법으로 구문 분석합니다(참조$IFS) 이는 일반적으로 우리가 원하는 것이 아닙니다.

반대로 확장을 큰따옴표로 묶으면(즉 "${CMD[@]}", 배열의 모든 요소가 유지됩니다.) hello world second item와 의 차이점을 고려해보세요 "hello world" "second item".

예시:

$ LIST=("hello world" "second item")

$ for ITEM in ${LIST[@]}; do echo $ITEM; done
hello
world
second
item

$ for ITEM in "${LIST[@]}"; do echo $ITEM; done
hello world
second item

답변3

이렇게 하지 마십시오 $(: comment). 이것은 주석이 아닙니다. 서브쉘입니다. 대부분의 쉘에서는 완전히 새로운 쉘 프로세스입니다. 당신의 목표는덜하다귀하의 입력만 있으면 이것이 수행되는 작업입니다. 비록 말이 되지 않더라도 말입니다.

넌 할 수있어...

printf '<%s>\n' some args here ${-##*"${--

                my long comment block

                }"}  and "more ${-##*"${--

                and another one in the
                middle of the quoted string
                there shouldn\'t b\e any special &
                (character) `echo issues here i hope >&2`
                basically anything that isn\'t a close \}
                $(echo the shell is looking for one >&2)
                }$(echo "}'"\" need backslash escaping >&2
                                )${-##*${--

                nesting is cool though

             }}"}here too"

}'" need backslash escaping
<some>
<args>
<here>
<and>
<more here too>

기본적으로 무슨 일이 일어나고 있는지 쉘이 대체를 수행하고 있다는 것입니다. $-매번 두 번씩 특수 쉘 매개변수의 값을 대체합니다 . 어쨌든 짧은 문자열이지만언제나설정 및 내부 대체는 외부에서 제거된 패턴으로 해석됩니다.아니요확장형을 사용하면 괄호 안의 내용으로 확장됩니다 -.

여기:

bash -x <<""
printf %s\\n '${-##*"'${-- a set param doesn\'t expand to this optional text }'"}'

+ printf '%s\n' '${-##*"hxB"}'
${-##*"hxB"}

바라보다? 그래서 크기가 두 배로 커진 거죠. 쉘이 매개변수가 설정된 것을 발견하면 선택적 확장 필드의 거의 모든 내용이 삭제되고 전체 값으로 확장되어 자체적으로 제거되므로 아무것도 없습니다. 대부분의 쉘에서는 따옴표를 이스케이프 처리할 필요조차 없지만 bash필수입니다.

더 좋은 점은 다음과 같습니다.

COMMENT=
echo      ${COMMENT-"
           this will work the same way
           but the stripping isn\'t
           necessary because, while
           the variable is set, it is also
           empty, and so it will expand to
           its value - which is nothing
           "} this you\'ll see

this you'll see

관련 정보