O problema é simplesmente o seguinte:
watch "psql -d postgresql://user:pass@host:5432/dbname -c 'select id,name from table where name <> 'not available' order by id;'"
esta 'not available'
comparação tem que ser entre aspas simples como é para o Postgres. Mas não consigo descobrir uma maneira de escapar dessas aspas simples corretamente, pois o comando psql (quer dizer, o select...
) já está entre aspas simples e também está dentro das aspas duplas exigidas pela chamada de psql
for watch.
Como resolver isso?
Eu quase vi todos os erros de sintaxe possíveis usando \
ou várias aspas duplas/simples para escapar dessas aspas simples.
Você não pode escapar de aspas simples dentro de aspas simples. Você pode, no entanto, fingir com:
Explicação: isso é uma aspa simples final (ou seja, para encerrar a cotação atual), seguida por uma aspa simples com escape e, em seguida, iniciar as aspas simples novamente. funciona da mesma forma que, digamos,
'a'b'c'
(citadoa
, depois sem aspas,b
depois entre aspasc
- todos juntos, isso é apenasabc
... e'a'\''b'
é apenasa'b
)(novas linhas adicionadas para melhorar a legibilidade. o comando sql funcionará da mesma forma com ou sem elas)
Nota: ao usar postgres (ou sqlite ou mysql, etc) é melhor usar uma linguagem que suporte placeholders, então você não precisa se preocupar em citar. Suas CLIs são boas para consultas interativas e alguns scripts (em SQL, não sh), mas a citação aninhada necessária para passar o código sql de sh é desajeitada e fácil de errar (não impossível, apenas muito mais esforço do que seria em outras linguagens ).
por exemplo, em perl DBI (não incluí nenhuma das coisas de login padrão, apenas o select com uma instrução preparada e um espaço reservado):
O
?
é um espaço reservado, o DBI o substituirá pelo valor que você fornecer - citando-o automaticamente , se necessário, dependendo do tipo de dados da coluna. ou seja, apenas forneça os dados para a coluna, deixe-o se preocupar em citar e escapar.BTW, você pode ter mais de um, você só precisa fornecer os tipos certos de argumentos na ordem certa. Além disso, alguns drivers DBI - incluindo DBD::Pg - permitem que você use marcadores de posição nomeados como
:name
ou marcadores de posição numerados como$1
,$2
- eles parecem os mesmos e funcionam aproximadamente da mesma forma que os parâmetros posicionais do shell, mas não são, são marcadores de posição em uma instrução sql)shell é uma linguagem terrível para qualquer coisa que não seja apenas alimentar dados e/ou nomes de arquivos em outros programas e coordenar a execução de outros programas. Qualquer coisa, mesmo moderadamente complicada, será um PITA devido ao cuidado e atenção que você deve prestar às questões de citação, espaço em branco, divisão de palavras etc. Você encontrará os mesmos tipos de problemas com aspas aninhadas em
ssh
comandos ou em umfind .. -exec sh -c '...' {} +
comando e muitas outras instâncias em que você precisa aninhar vários níveis de aspas.Também é possível usar um heredoc e evitar o escape: