폴리글랏 .bat - 파이썬, 자바스크립트, 루아

Twitter icon류광, 2024-03-30 14:03
이번 글에서는 Windows 콘솔(명령줄) 환경의 스크립트 파일인 .bat 파일에 다른 스크립팅 언어의 코드를 담아서 실행하는 폴리글랏 .bat을 살펴봅니다. 구체적으로, 파이썬, 자바스크립트, 루아의 예를 제시합니다.

이번 글에서는 Windows 콘솔(명령줄) 환경의 스크립트 파일인 .bat 파일에 다른 스크립팅 언어의 코드를 담아서 실행하는 폴리글랏 .bat을 살펴봅니다. 구체적으로, 파이썬, 자바스크립트, 루아의 예를 제시합니다.

폴리글랏polyglot은 여러 가지 언어를 사용한다, 여러 언어에 통한다 등의 뜻을 가진 단어인데요. 프로그래밍의 맥락에서 "폴리글랏 코드"라고 하면 하나의 소스 코드가 여러 가지 언어로 해석 또는 번역되는 것을 말합니다.

서로 다른 언어로 같은 일을 수행하는 고도의 폴리글랏 코드도 있지만, 이 글의 예들은 그 정도는 아니고요. 다만, <언어 실행기> <스크립트> 형태가 아니라 그냥 <스크립트>.bat으로 스크립트를 실행할 수 있어서 자동화 등 일부 응용에서 나름 유용합니다.

그럼 파이썬부터 시작하죠.

파이썬용 bat 파일

다음은 파이썬 스크립트로, .bat 파일로도 해석되는 .bat 파일의 예입니다. python이 파이썬 실행 프로그램이고 시스템 경로에 있다고 가정합니다.

ex-python.bat

@echo off & python -x "%~f0" %* & goto :eof

print("Hello world - Python")

이 폴리글랏 .bat은 파이썬 실행기의 -x 옵션을 활용합니다. -x 옵션이 지정되면 파이썬은 첫 줄을 무시하고 둘째 줄부터 해석을 시작하므로, 파이썬 문법에는 맞지 않는 @echo off 등이 아무런 문제를 일으키지 않습니다.

Windows 콘솔의 관점에서는 첫 줄에서 파이썬 실행기를 실행한 후 goto :eof에서 이 파일의 마지막으로 점프하므로, 파이썬 코드 print("Hello world")는 아무런 문제를 일으키지 않습니다.

자바스크립트용 bat 파일

다음은 자바스크립트 스크립트로도, .bat 파일로도 해석되는 .bat 파일의 예입니다. 이 예에서 실행기는 node이지만, deno run 등도 가능할 것입니다. 역시 해당 실행기가 시스템 경로에 있다고 가정합니다.

ex-js.bat

0</* ::
@node "%~f0" %* & goto :eof
*/0;

console.log("Helllo world - JavaScript")

첫 줄의 작동 원리를 제가 100% 이해하지는 못했는데요. 결론만 이야기하면, Windows 콘솔은 어찌어찌해서 첫 줄을 하나의 이름표로 취급한다고 합니다. 그래서 첫 줄은 아무 효과도 내지 않습니다. 그다음은 파이썬의 예처럼 그냥 이 파일과 추가 인수들로 해당 실행기로 호출하고 끝내는 것입니다.

자바스크립트 실행기의 관점에서는, 첫째 줄에서 셋째 줄까지는 블록 주석(/* ... */)이 제외되어서 0<0;이 됩니다. 이것은 그냥 거짓으로 평가되는 하나의 부울 표현식으로 이루어진 자바스크립트 문장이므로 아무런 부수 효과도 없습니다.

이 예의 패턴은, 표현식만으로도 유효한 문장이 되며 그런 문장이 아무런 부수 효과(특히 표준 출력)도 발생하지 않는 다른 언어에도 사용할 수 있습니다.

루아용 bat 파일

마지막으로 루아Lua 버전을 봅시다. 예전 글 "루아 5.2 이상에서 루아 스크립트를 실행 가능한 .bat 파일에 담는 방법"에 나온 코드를 좀 더 간단하게 만든 것입니다. 루아 5.2 이상에서 작동합니다. 루아 5.1 이하는 언급한 예전 글을 보세요.

ex-lua.bat

::lua::--[[
@lua "%~f0" %* & goto :eof
--]]

print"Hello world - Lua"

예전 글에서 언급했듯이, ::lua::--[[는 .bat 파일의 문법에서 이름표(레이블)이므로 Windows 콘솔은 아무것도 수행하지 않습니다. Windows 콘솔은 그다음 행으로 넘어가서, 이 bat 파일의 전체 경로(%~fp0)와 기타 명령줄 인수들로 루아 실행 프로그램(lua; 역시 시스템 경로에 있다고 가정)을 호출합니다.

루아 실행기의 관점에서 첫 줄의 ::lua::는 .bat의 경우처럼 하나의 이름표입니다. 그리고 그다음의 --[[에서 셋째 줄 --]] 까지는 블록 주석입니다. 따라서 bat을 위한 lua %~f0 ... 부분은 완전히 무시됩니다.

그다음부터는 그냥 보통의 루아 스크립트로 작동합니다. print"Hello world - Lua"에 의해 표준 출력에 Hello world - Lua가 출력됩니다.

주의 사항 하나

이런 폴리글랏 .bat도 기본적으로는 .bat 스크립트이므로, 다른 .bat 스크립트에서 호출 시 call을 사용해야 함을 주의하세요. 예를 들어 다음과 같은 .bat 파일은 예상과는 다르게 작동합니다.

run-all.bat

@echo off
ex-pyton.bat
ex-js.bat
ex-lua.bat

이것을 실행하면 Helloworld - PythonHelloworld - Java, Helloworld - Lua 세 줄이 출력될 것 같지만, 실제로는 Helloworld - Python 하나만 출력됩니다. bat 파일 안에서 다른 bat 파일을 실행하면 그 시점에서 원 bat 파일의 실행이 끝나기 때문입니다(이는 DOS 시절 때부터 이어져온 Windows 콘솔 환경의 특성입니다).

제대로 하려면 다음처럼 call 명령을 사용해야 합니다.

run-all.bat

@echo off
call ex-pyton.bat
call ex-js.bat
call ex-lua.bat
태그: 프로그래밍 루아 파이썬 자바스크립트

comments powered by Disqus