Eu preciso produzir arquivos de configuração JSON com echo
e tee
chamados do meu script Python.
Por tentativa e erro, descobri que tenho que usar aspas simples. No entanto, não entendo todo o comportamento que encontrei ao usar o run()
. O código a seguir imprime minhas perguntas:
#!/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)
Eu uso Bash como meu shell. Por que as aspas duplas são diferentes quando feitas no meu shell Bash em comparação com a execução do Python. Não estou acessando meu shell Bash especificando
shell=True
em run()
?
PS Eu sei que gerar JSON com json
módulo é uma maneira de fazer isso, mas no meu caso é principalmente copiar JSON já existente de meus arquivos de configuração de backup. Quero evitar a leitura desses arquivos JSON em uma string em meu script - o script deve ser executado no sistema operacional recém-reinstalado, onde esses backups não estarão disponíveis inicialmente. É por isso que preciso ter muitas variáveis de string em minha string Python que armazenam esses arquivos de configuração JSON
Sobre as aspas, deixando de lado as novas linhas, isto:
atribui a string
{ "alt-speed-down": 50, }
à variável. Então, quando você executarun(f"""echo "{conf_file}" """, shell=True)
, o shell vê a stringque é diferente daquele com aspas simples:
Aqui, as barras invertidas escapam das aspas duplas e são removidas pelo Python, então isso é equivalente ao primeiro. Escapar das aspas não é necessário aqui, mas seria se você tivesse feito
"{ \"alt-speed-down\": 50, }"
isso.Se você quiser ter as barras invertidas intactas na string Python, você precisa usar
r''
strings, por exemplor'{ \"alt-speed-down\": 50, }'
(ou o mesmo com aspas duplas,r"{ \"alt-speed-down\": 50, }"
na verdade também funciona, e as barras invertidas não são removidas, mesmo que sejam necessárias para não terminar a string citada.)No shell, as barras invertidas não são processadas entre aspas simples, então
passa para
echo
a string\"this is quoted\"
. Embora algumas implementações deecho
processassem escapes como\n
, independentemente do que acontece no processamento da linha de comando do shell.Considerando que com
você não tem contrabarras à vista.
Resumindo, as regras de citação são diferentes entre os shells e o Python.
Ver:
Como mencionado nos comentários, provavelmente há maneiras melhores de produzir JSON (ou YAML, ou qualquer outro) a partir do Python do que imprimir strings manualmente. Ex: o
json
módulo: