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

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

답변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

관련 정보