Python에서 이스케이프된 큰따옴표(shell=True)가 Bash와 다른 이유는 무엇입니까?

Python에서 이스케이프된 큰따옴표(shell=True)가 Bash와 다른 이유는 무엇입니까?

echoPython 스크립트를 사용하여 JSON 구성 파일을 생성하고 호출해야 합니다 .tee

시행착오를 거쳐 작은따옴표를 사용해야 한다는 사실을 알게 되었습니다. 그러나 저는 Python을 사용할 때 발생하는 모든 동작을 이해하지 못합니다 run(). 다음 코드는 내 문제를 인쇄합니다.

#!/usr/bin/env python3

from subprocess import run

conf_file="""{
"alt-speed-down": 50,
}"""
print("Question 1. It does not work with double quotes. Why?")
run(f"""echo "{conf_file}" """, shell=True)
print("It works with single quotes.")
run(f"""echo '{conf_file}'""", shell=True)
conf_file="""{
\"alt-speed-down\": 50,
}"""
print("""Question 2. It does not work with double quotes, even when I escape the quotes.
Whereas when I type in my shell: 
echo "\"This is a quoted string.\"" 
it works. Why? 
""")
run(f"""echo "{conf_file}" """, shell=True)
print("""Question 3. It works with single quotes, even with escaped quotes. 
whearas when I type in my shell:
echo '\"this is quoted\"' 
I get the backslashes printed. Why aren't
the backslashes printed when called with Python's run()?""")
run(f"""echo '{conf_file}'""", shell=True)

저는 Bash를 쉘로 사용합니다. Bash 셸에서 큰따옴표를 이스케이프하는 것과 Python에서 큰따옴표를 이스케이프하는 것이 왜 다른가요? shell=True사양을 통해 Bash 쉘에 액세스 하지 않습니까 run()?

추신: 모듈을 사용하여 JSON을 생성하는 것이 이를 수행하는 한 가지 방법이라는 것을 알고 있지만 json제 경우에는 주로 백업된 구성 파일에서 기존 JSON을 복사하는 작업이 포함됩니다. 이러한 JSON 파일을 스크립트의 문자열로 읽는 것을 피하고 싶습니다. 스크립트는 처음에 해당 백업을 사용할 수 없는 새로 다시 설치된 OS에서 실행되도록 설계되었습니다. 그렇기 때문에 이러한 JSON 구성 파일을 저장하려면 Python 문자열에 많은 문자열 변수가 필요합니다.

답변1

따옴표와 관련하여 줄 바꿈을 제외하면 다음과 같습니다.

conf_file="""{ "alt-speed-down": 50, }"""

{ "alt-speed-down": 50, }변수에 문자열을 할당합니다 . 그런 다음 실행하면 run(f"""echo "{conf_file}" """, shell=True)쉘에 해당 문자열이 표시됩니다.

echo "{ "alt-speed-down": 50, }"

이는 작은따옴표와 다릅니다.

echo '{ "alt-speed-down": 50, }'

conf_file="""{ \"alt-speed-down\": 50, }"""

여기서 백슬래시는 큰따옴표를 이스케이프하고 Python에 의해 제거되므로 첫 번째 것과 동일합니다. 여기서는 따옴표를 이스케이프 처리할 필요가 없지만, "{ \"alt-speed-down\": 50, }"따옴표가 있는 경우 이스케이프 처리해야 합니다.

Python 문자열에서 백슬래시를 그대로 유지하려면 (또는 큰따옴표와 동일한 r''문자열을 사용해야 합니다 . 이는 실제로 작동하며, 백슬래시는 따옴표 문자열로 끝나지 않아야 하는 경우에도 제거되지 않습니다.)r'{ \"alt-speed-down\": 50, }'r"{ \"alt-speed-down\": 50, }"


셸에서는 작은따옴표 안의 백슬래시가 처리되지 않으므로

echo '\"this is quoted\"' 

echo문자열 로 전달되었습니다 \"this is quoted\". 그러나 일부 구현에서는 쉘 명령줄 처리에서 발생하는 상황에 관계없이 echo이스케이프 문자(예: )를 처리합니다 .\n

그리고

run(f"""echo '{conf_file}'""", shell=True)

백슬래시를 볼 수 없습니다.

즉, 셸과 Python에서는 인용 규칙이 다릅니다.

바라보다:


주석에서 언급했듯이 Python에서 JSON(또는 YAML 등)을 생성하는 것이 문자열을 수동으로 인쇄하는 것보다 낫습니다. 예를 들어 json모듈은 다음과 같습니다.

>>> import json
>>> obj = {}
>>> obj["alt-speed-down"] = 50
>>> json.dumps(obj)
'{"alt-speed-down": 50}'

관련 정보