Почему этот фрагмент с shebang #!/Bin/sh и exec python внутри 4 одинарных кавычек работает?

Я пытаюсь понять один из ответов на этот вопрос:

Невозможно передать аргумент python с "#!/usr/bin/env python"

#!/bin/sh
''''exec python -u -- "$0" ${1+"[email protected]"} # '''

Это хорошо работает, но я не понимаю, почему он работает с четырьмя тиками в начале этой строки, а не с тремя.

Кроме того, почему хэш в конце этой строки?

Ответ 1

Python поддерживает тройные кавычки:

'''something'''

Оболочка поддерживает только строки с одной кавычкой:

'something'

Используя четыре кавычки, sh видит, что в качестве 2 пустых строк, но Python видит первые три в качестве начала строки с тремя кавычками и включает четвертый как часть строкового значения.

Остальная часть строки интерпретируется как команда sh, но как часть строки Python.

Затем # формирует комментарий до sh, но он все еще является строкой для Python, закрывая его закрывающей тройной кавычкой.

Итак, суммируем:

  • sh видит: пустая строка ('') - пустая строка ('') - команда (exec python -u -- "$0" ${1+"[email protected]"}) - комментарий (# ''')
  • Python видит: строковый литерал с тремя кавычками (содержащий символы 'exec python -u -- "$0" ${1+"[email protected]"} #)

Итак sh выполняет эту команду, заменяя себя python -u -- на имя script и остальные аргументы командной строки, а Python читает этот файл и просто видит исходный строковый литерал, который не собирается в любом месте.

Поскольку это первый строковый литерал в файле, он будет установлен как docstring для модуля __main__, но это вряд ли имеет значение, если это основной script.

Ответ 2

Я просто использую:

#!/bin/sh
''':'
exec python -tt "$0" "[email protected]"
'''
# The above shell shabang trick is more portable than /usr/bin/env and supports adding arguments to the interpreter (python -tt)