작은따옴표와 큰따옴표는 "bash" 또는 "echo"로 처리됩니까?

작은따옴표와 큰따옴표는 "bash" 또는 "echo"로 처리됩니까?

다음과 같은 작업을 수행할 때:

echo 'Hello World'

또는 다음과 같습니다:

x=12345
echo "x is: $x"

첫 번째 예에서 echo명령은 receive 입니까 'Hello World', 아니면 receive 입니까 Hello World?

두 번째 예에서 echo명령은 receive 입니까 "x is: $x", 아니면 receive 입니까 x is: 12345?

그래서 기본적으로 제 질문은: 작은 따옴표와 큰 따옴표가 bash에 의해 처리됩니까 아니면 에 의해 처리됩니까 echo?

답변1

따옴표, 변수 확장, 와일드카드 및 기타 모든 항목에 언급된 내용확장에 대한 bash 매뉴얼bash로 처리됩니다.

예를 들어, bash 명령을 실행하면 bash는 명령을 구문 분석하여 명령을 실행하는 데 하나의 인수(예: )가 echo "x is: $x"필요한지 확인합니다 . 가 주어지면 bash는 두 개의 인수로 실행됩니다. 그리고 — 이것이 바로 따옴표 안의 두 공백이 유지되는 이유입니다(수정되지 않은 인수를 에코 인쇄하는 부분임). 그러나 따옴표 밖의 두 공백은 유지되지 않습니다(셸의 ​​경우 두 공백 공백) 인수를 분리하는 것은 단일 인수만큼 좋으며 항상 중간에 공백을 인쇄합니다.echox is: 12345echo "x is" "$x"echox is12345echo

이 명령(또는 다른 명령)은 어떤 쉘 명령이 인수를 생성했는지 또는 쉘이 실제로 관련되었는지 echo알 수 없습니다 . x is: 12345다음은 이 매개변수를 생성하는 몇 가지 명령 예입니다.

echo "x is: 12345"
echo 'x is: 12345'
echo x\ is:\ 12345
echo "x is: $x"
echo 'x is:'\ "$x"
echo "$(echo "x ")is: $x"
# Assume there is no other file whose name begins with x in the current directory
touch "x is: $x"; echo x*

아니면 exec "echo", "x is: 12345"Perl이나 execlp("echo", "echo", "x is: 12345")C 와 같은 언어일 수도 있습니다.

이는 모든 명령에 적용됩니다. 동일한 원칙이 다른 셸에도 적용되지만 각각의 확장 세트는 약간(또는 크게) 다릅니다.

반면에,옵션명령으로 처리됩니다. 예를 들어, ls -l -tbash ls -l "-t"(또는 유사한 셸)에서는 둘 다 ls두 개의 인수 -l-t. 그렇기 때문에 ls.txt라는 파일에 대한 정보를 표시하기 위해 실행하려는 경우 어떤 형태의 셸 인용도 도움이 되지 않습니다 -t. 를 사용하여 이를 수행할 수 있습니다 ls -l -- -t. 즉, --매개변수로 전달하면 됩니다. 이는 대부분의 명령이 따르는 규칙입니다. 뒤에 오는 모든 명령은 --옵션으로 구문 분석되지 않습니다. 다시 말하지만, 이는 명령의 기능입니다. 쉘에서 선행 대시는 특별한 것이 아닙니다.

까다로울 수 있는 한 가지는 백슬래시입니다. Bash 및 기타 쉘에서 따옴표 밖의 백슬래시는 다음 문자가 특별한 의미를 잃음을 의미합니다. 예를 들어, 백슬래시 앞에 오는 각 문자는 특별한 의미( 의 경우 인용 구문 , 단어 구분 기호의 경우 공백) 를 잃기 때문에 echo \"x\ is:\ 12345\"인쇄합니다 . 그러나 일부 명령은 백슬래시도 해석합니다. 그럴 경우 백슬래시가 도달하는지 확인해야 합니다. 예를 들어, bash에서 명령은 기본적으로 백슬래시를 문자 그대로 인쇄하지만 옵션 을 전달 하거나 먼저 실행 하면 자체 이스케이프 시퀀스가 ​​있습니다 . 특별 취급 백슬래시입니다). 예를 들어, 인쇄할 때 -newline-을 인쇄하세요 . 왜냐하면 에 대한 "newline"을 의미하기 때문입니다 . 반면에 인쇄 이후는 쉘에 의해 확장되어 "다음 문자를 인용한다"는 의미를 갖습니다."x is: 12345""echo-eshopt xpg_echoechoechoecho 'a\nb'a\nbecho -e 'a\nb'ab\necho -eecho a\nbanb\n\

또한 여러 셸이 관련되어 있는 경우(예: SSH 사용) 주의하세요. ssh쉘에서 실행 하면 로컬 쉘은 평소와 같이 명령을 구문 분석합니다. SSH 클라이언트는 옵션이 아닌 인수를 중간 공백과 연결하고 결과 문자열을 SSH 서버로 보냅니다. SSH 서버는 이 문자열을 원격 셸에 전달합니다. 이는 터미널이나 쉘 스크립트에 입력한 내용과 원격 시스템에서 실행되는 내용 사이에 두 번의 전체 쉘 확장 라운드가 있음을 의미합니다.

답변2

귀하의 예에서 쉘은 따옴표를 사용합니다.

쉘(모든 쉘)이 취하는 첫 번째 단계는 다음과 같습니다.명령줄을 토큰으로 분할.

첫 번째 단계7.3장: 명령줄 처리분열입니다. "그림 7.1: 명령줄 처리 단계"도 참조하세요.

각 마크는 라인의 일부입니다. 각 토큰은 다음과 같을 수 있습니다.일부 확장또는 다른 토큰.

분할은 대부분 메타 문자에서 수행되며(공백은 메타 문자이며 가장 일반적으로 사용됨) 인용하면 분할이 수정됩니다. 작은따옴표는 모든 문자(공백 포함)를 단일 토큰으로 그룹화합니다.

printf를 사용하여 분할을 "볼" 수 있습니다.

$ printf '<%s>\n' echo 'Hello World'
<echo>
<Hello World>

큰따옴표도 문자를 그룹화하지만 일부 내부 확장을 허용합니다.

$ x=12345
$ echo "x is: $x"
x is: 12345
$ printf '%s' echo "x is: $x"
<echo>
<x is: 12345>

따옴표는 다음과 같이 나타날 수도 있습니다.

$ echo $(printf '"%s" ' "Hello World")
"Hello World"

그러나 셸을 기준으로 분할하면 흥미로운 반전이 추가됩니다.

$ printf '<%s>\n' echo $(printf '"%s" ' "Hello World")
<echo>
<"Hello>
<World">

명령 확장 결과에 따라 분할이 수행됩니다. Quote 명령 확장은 분할을 방지할 수 있습니다.

$ printf '<%s>\n' echo "$(printf '"%s" ' "Hello World")"
<echo>
<"Hello World" >

따옴표의 또 다른 소스는 백슬래시입니다. 공백을 인용하면 해당 문자가 일반 문자로 작동하게 됩니다(메타 문자를 나누는 대신).

$ printf '<%s>\n' echo Hello\ World
<echo>
<Hello World>

관련 정보