`//`로 시작하는 Shebang?

`//`로 시작하는 Shebang?

다음 스크립트( )에 대해 혼란스럽습니다 hello.go.

//usr/bin/env go run $0 $@ ; exit

package main
import "fmt"
func main() {
    fmt.Printf("hello, world\n")
}

실행할 수 있습니다. (MacOS X 10.9.5)

$ chmod +x hello.go
$ ./hello.go
hello, world

로 시작하는 shebang에 대해 들어본 적이 없습니다 //. 그리고 스크립트 상단에 빈 줄을 삽입해도 여전히 작동합니다. 이 스크립트가 작동하는 이유는 무엇입니까?

답변1

이것은 shebang이 아니며 기본 쉘에 의해 실행되는 스크립트일 뿐입니다. 쉘은 첫 번째 줄을 실행합니다.

//usr/bin/env go run $0 $@ ; exit 

이는 go이 파일의 이름으로 호출되므로 결과적으로 이 파일은 go 스크립트로 실행된 다음 파일의 나머지 부분을 보지 않고 쉘이 종료됩니다.

그런데 왜 그냥 또는 적절한 shebang //대신 에 시작해야 할까요 ?/#!

이는 파일이 유효한 go 스크립트여야 하기 때문입니다. 그렇지 않으면 go가 불평할 것입니다. go에서 문자는 //주석을 나타내므로 go는 첫 번째 줄을 주석으로 보고 이를 해석하려고 시도하지 않습니다. 그러나 문자는 #주석을 나타내지 않으므로 일반적인 shebang에서는 go가 파일을 해석할 때 오류가 발생합니다.

이러한 구문의 이유는 한 단계를 거치지 않고 쉘 스크립트이자 go 스크립트인 파일을 빌드하기 위한 것입니다.

답변2

기본 실행 파일은 /bin/sh 스크립트로 간주되기 때문에 실행됩니다. 즉, 특정 쉘을 지정하지 않은 경우 #!/bin/sh입니다.

//는 경로에서 무시됩니다. 단일 '/'로 간주할 수 있습니다.

따라서 첫 번째 줄이 있는 쉘 스크립트가 있다고 생각할 수 있습니다.

/usr/bin/env go run $0 $@ ; exit

이 줄은 무엇을 합니까? 매개변수 'go run $0 $@'을 사용하여 'env'를 실행합니다. 'go'는 명령이고 'run $0 $@'은 인수이고 나중에 스크립트를 종료합니다. $0은 이 스크립트 이름입니다. $@는 원본 스크립트 인수입니다. 따라서 이 줄은 인수를 사용하여 이 스크립트를 실행하는 go를 실행합니다.

주석에서 지적한 것처럼 두 개의 슬래시가 구현에 따라 정의되고 이 스크립트가 세 개 이상의 슬래시를 지정하면 이 스크립트가 POSIX에 적합하다는 매우 흥미로운 세부 사항이 있습니다. 인용하다http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html경로에서 슬래시를 처리하는 방법에 대한 자세한 내용을 참조하세요.

$@ 스크립트에는 또 다른 실수가 있습니다. 대신 "$@"을 사용하는 것이 옳습니다. 그렇지 않으면 매개변수에 공백이 포함되어 있으면 여러 매개변수로 분할되기 때문입니다. 예를 들어 "$@"를 사용하지 않으면 공백이 포함된 파일 이름을 전달할 수 없습니다.

이 특정 스크립트는 분명히 '//'가 '/'와 같다는 생각에 의존합니다.

답변3

이것은 C++에서 작동합니다(그리고 C가 주석을 허용하는 경우 // C).

//usr/bin/env sh -c 'p=$(expr '"_$0"' : "_\(.*\)\.[^.]*"); make $p > /dev/null && $p'; exit

관련 정보