Я знаю, это звучит странно, и это так (это была не моя идея).
Из конечной точки API я получаю скрипт bash или python (в виде строки), а затем мне нужно его запустить. Мой вопрос: есть ли способ узнать, какой из двух языков это?
Поскольку вы уже используете Python, import ast; ast.parse(script_text) будет простым способом проверить, является ли ваша строка допустимой для Python.
С точки зрения API, лучше всего было бы, чтобы клиент рассказал вам, что это за скрипт, вместо того, чтобы ожидать, что вы в нем разберетесь. Это имеет дополнительное преимущество: если вы когда-нибудь захотите расширить эту (несколько сомнительную) идею, чтобы охватить больше языков (perl, csh, Ruby,...), то это будет относительно просто.
@JohnBollinger, я полностью согласен с твоей точкой зрения, но, к сожалению, у меня нет никакой власти, кроме API. :(
Тогда пора отступить. Как минимум, вполне разумно настаивать на том, чтобы ввод имел соответствующую маркировку, идентифицирующую язык. Линия шебанг была бы для этого естественным выбором.
Продолжая точку зрения @JohnBollinger, я бы сказал, что строка shebang является необходимой частью действительного сценария оболочки, поэтому все, что ее не имеет, можно немедленно исключить из числа сценариев оболочки. (Но обратите внимание, что допустимая программа Python вполне может иметь строку shebang, поэтому вы не можете просто проверить наличие/отсутствие, чтобы определить, что это такое.)
Это принципиально НЕВОЗМОЖНО, потому что сценарий может быть действительным на нескольких языках (другими словами, на полиглоте). Например, flower.codes/2023/12/30/polyglot-hello-world.html работает как на Python, так и на Bash, а также на C, Julia и CoffeeScript!
Отвечает ли это на ваш вопрос? python: как проверить синтаксис файла/скрипта Python, не выполняя его?
Какой бы ни была первоначальная причина принятия сценариев от службы (сейчас 2024 год), как вы можете справиться с риском того, что злоумышленники захватят службу и начнут кормить вас плохими сценариями?






import re
def identify_script_type(script_text):
# Common Python keywords and constructs
python_keywords = [
"def ", "import ", "print(", "exec(", "except ", "try:", "lambda ",
"self.", "class ", "global ", "with ", "yield ", "async ", "await "
]
# Common Bash keywords and constructs
bash_keywords = [
"#!/bin/bash", "echo ", "function ", "if [[", "fi", "done", "do ",
"then", "elif", "else", "case ", "esac", "for ", "while ", "in ", "&&",
"||", "$(", "${", "`", "source ", ". ", "sudo ", "export ", "unset ",
"trap ", "read ", "exit "
]
# Check for common Python keywords
for keyword in python_keywords:
if keyword in script_text:
return "python"
# Check for common Bash keywords
for keyword in bash_keywords:
if keyword in script_text:
return "bash"
# If no specific keywords are found, return unknown
return "unknown"
# Example usage
script_text_python = """
def run():
print("Hello, Python!")
"""
script_text_bash = """
#!/bin/bash
echo "Hello, Bash!"
"""
print(identify_script_type(script_text_python)) # Output: python
print(identify_script_type(script_text_bash)) # Output: bash
Этого не будет. работа. Несмотря на то, что эти шаблоны обычно встречаются в Python и Bash, они могут встречаться и в том, и в другом. Например, в Python также иногда используется функция exit().
Это может быть хорошо в качестве эвристического подхода для некоторых хорошо известных входных данных, но, по моему мнению, в целом он слишком ненадежен, чтобы работать. Одни только комментарии разрушают этот подход.
Чтобы проверить, содержит ли строка действительный bash, используйте этот код:
Линукс и Юникс:
import sh
bash_code = "your_bash_code_here"
result = sh.bash("-n", bash_code, _ok_code=[0])
if result.exit_code == 0:
pass
else:
pass
Окна:
import subprocess
bash_code = "your_bash_code_here"
result = subprocess.run(["pylint", "--errors-only", "-", bash_code], capture_output=True, text=True)
if result.returncode == 0:
print("The string contains valid Bash code.")
else:
print("The string contains invalid Bash code.")
Чтобы проверить, содержит ли строка действительный Python, используйте этот код:
import ast
python_code = "your_python_code_here"
try:
ast.parse(python_code)
pass
except SyntaxError as e:
pass
Как здесь отличить синтаксически неверный код bash от действительного кода bash, который просто возвращает ненулевой код выхода?
Попросите парсер проверить его валидность. Shellcheck может быть для сценария оболочки.