변수 대체를 사용한 평가 및 실행

변수 대체를 사용한 평가 및 실행

서버를 시작하는 명령문을 실행하고 싶습니다. 이를 위해 시작할 서버를 결정하는 환경 변수가 있습니다. 저는 다음 명령을 시작점으로 삼았습니다.

eval "exec gunicorn --chdir /this/dir package.sub:call_main() -b 0.0.0.0:80"

시작해야 할 서버가 여러 개 있으므로 스크립트를 매개변수화하고 싶습니다. 검색을 좀 해보니 그 인용문이 다음과 같다는 것을 알았습니다.추가의. 그래서 내가 지금 가지고 있는 것은 다음과 같습니다.

APP=main
eval exec gunicorn --chdir /this/dir package.sub:call_${APP}() -b 0.0.0.0:80

이상적 syntax error near unexpected token '('으로는 이와 같은 기본 매개변수를 갖고 싶지만 ${APP:-main}구문 오류 문제가 해결되면 가능하다고 생각합니다.

위의 진술에 잘못된 것이 있습니까? 또한, eval여기에는 이것이 필요합니까?exec

답변1

두 번째 코드에서는 매개변수 주위의 큰따옴표를 제거했습니다 eval. 그러지 마세요. 이를 제거하면 ()쉘이 특별해집니다(하위 쉘이 시작됨).

대신에:

app=main
eval "exec gunicorn --chdir /this/dir package.sub:call_$app'()' -b 0.0.0.0:80"

eval문자열을 다시 평가할 때 여기에서 괄호를 인용해야 합니다. $app호출 전에 변수 확장이 수행됩니다 .eval

또는,

app=main
eval "exec gunicorn --chdir /this/dir 'package.sub:call_$app()' -b 0.0.0.0:80"

이게 더 좋아 보일 수도 있어요.

및 는 변수 이름(예: )에서 유효한 바로 다음 문자를 제외하고 ${APP}모든 면에서 동일합니다 . 여기서는 필요하지 않습니다. 또한 기존 환경 변수와의 예기치 않은 충돌을 방지하려면 소문자 변수 이름을 사용하십시오.$APP"${APP}x"{...}

나는 여기에 필요하지 eval않다고 생각합니다 exec. 문자열은 다음을 사용하여 eval재평가할 필요가 없는 것 같습니다.exec바꾸다현재 쉘 프로세스 gunicorn(이것이 당신이 원하는 것인지 모르겠습니다).

충분할 수도

app=main
gunicorn --chdir /this/dir "package.sub:call_$app()" -b 0.0.0.0:80

큰따옴표에 주의하세요.

관련된:

답변2

당신은 복잡한 작업을 수행하고 있습니다. 쉘은 11개의 패스를 만들어야 합니다(그리고 각 패스는 다음 단계를 진행하기 위해 입력을 파괴합니다).

귀하의 코드는

APP=main
eval exec gunicorn --chdir /this/dir package.sub:call_${APP}() -b 0.0.0.0:80

이해하려면 eval을 제거하세요.

exec gunicorn --chdir /this/dir package.sub:call_${APP}() -b 0.0.0.0:80

참고: 첫 번째 예와 유사하게 및 큰따옴표를 제거하면 eval여전히 동일한 출력을 얻을 수 있습니다.

이제 예약했습니다 ()(이 경우 토큰이 잘못 해석될 수 없기 때문에 특별합니다. 접두사가 없으면 명령 컨텍스트에 있지 않습니다(따라서 괄호를 사용하여 하위 쉘을 호출함). 참고: 이는 11단계로, 그리고 토큰화 순서를 보면 왜 이런 일이 일어나는지 알 수 있을 것입니다(그리고 쉘 파서는 오래 전에 설계되었으므로 쉽습니다).

따라서 ()를 다음 파서 단계로 전달하도록 쉘에 지시해야 합니다.

이스케이프( )를 사용할 수 있습니다 \.

exec gunicorn --chdir /this/dir package.sub:call_${APP}\(\) -b 0.0.0.0:80

또는 인용문:

exec gunicorn --chdir /this/dir package.sub:call_${APP}'()' -b 0.0.0.0:80

참고: "단어"(매개변수) 전체를 인용할 필요는 없으며 일부만 인용하면 됩니다. 그러면 작은따옴표가 필요하지 않습니다 ${APP}(확장 필요).

첫 번째 예에서는 큰따옴표로 인용할 수 있습니다.

eval "exec gunicorn --chdir /this/dir \"package.sub:call_main()\" -b 0.0.0.0:80"

이 방법으로 eval은 외부 따옴표를 제거하고 exec는 내부 따옴표를 봅니다(이스케이프되지 않음).

관련 정보