Oneliner для загрузки скрипта Lua из сети (Gist) и запуска в текущем контексте

У меня есть lua REPL, и я хотел бы запустить файл сценария lua, хранящийся в виде простого текста на HTTPS://URL, я понимаю os.execute() может запускать команды ОС, чтобы мы могли использовать curl и т.д., чтобы взять скрипт тогда load(), Можно ли это сделать в lua REPL одной строкой?

1 ответ

Решение

Примечание. Если вы собираетесь запускать исходный код непосредственно из Интернета, используйте https по крайней мере, чтобы избежать легких атак MitM.

Чтобы дать ответ на этот вопрос, так как Егор, вероятно, не будет публиковать его как таковой:

(loadstring or load)(io.popen("wget -qO- https://i.imgur.com/91HtaFp.gif"):read"*a")()

Почему это печатает Hello world:

loadstring or load должен быть совместим с различными версиями Lua, так как функции loadstring а также load были объединены в какой-то момент (5,2 я считаю). io.popen выполняет свой первый аргумент в оболочке и возвращает указатель файла на свой стандартный вывод.

"GIF" от Егора на самом деле не GIF (откройте это в вашем браузере: view-source:https://i.imgur.com/91HtaFp.gif) но простой текстовый файл, который содержит этот текст:

GIF89a=GIF89a
print'Hello world'

В основном GIF начинается с GIF89a и =GIF89a впоследствии это просто для создания действительного Lua, то есть вам не нужно использовать imgur или gifs, вы также можете использовать raw gists или github.

Теперь маловероятно, что os.execute доступен в песочнице, когда io.popen нет, но если это так, вы можете добиться однострочности (хотя и значительно дольше), используя os.execute и временные файлы

Давайте сначала запишем это, потому что в одной строке это будет немного сложно:

(function(u,f)
    -- get a temp file name, Windows prefixes those with a \, so remove that
    f=f or os.tmpname():gsub('^\\','')
    -- run curl, make it output into our temp file
    os.execute(('curl -s "%s" -o "%s"'):format(u,f))
    -- load/run temp file
    loadfile(f)()
    os.remove(f)
end)("https://i.imgur.com/91HtaFp.gif");

И вы можете легко сжать это в одну строку, удалив комментарии, вкладки и новые строки:

(function(u,f)f=f or os.tmpname():gsub('^\\','')os.execute(('curl -s "%s" -o "%s"'):format(u,f))loadfile(f)()os.remove(f)end)("https://i.imgur.com/91HtaFp.gif");
Другие вопросы по тегам