Quero esclarecer que não estou falando sobre como escapar caracteres no nível de interpretação do shell.
Tanto quanto eu posso dizer, apenas dois caracteres precisam ser escapados: %
e\
Para imprimir um literal %
, você deve escapá-lo com um precedente %
:
printf '%%'
Para imprimir um literal \
, você deve escapá-lo com um precedente \
:
printf '\\'
Existem outras instâncias em que eu precisaria escapar de um caractere para que ele fosse interpretado literalmente?
No argumento de formato de
printf
, apenas os caracteres%
e\
são especiais (não,"
não é especial e\"
não é especificado por POSIX).Mas, duas notas importantes .
Na maioria das
printf
implementações¹, são os valores de byte para\
e%
que são especiais e a especificação POSIX pode até ser interpretada como exigindo isso, pois exige que oprintf
utilitário seja uma interface para aprintf(3)
função C e nãowprintf(3)
por exemplo (como requer%.3s
truncar para 3 bytes e não 3 caracteres ).Em algumas codificações de caracteres, incluindo BIG5 e GB18030, existem centenas de caracteres que contêm a codificação de barra invertida e, para escapar daqueles para
printf
, você precisa inserir um\
antes de cada0x5c
byte na codificação desses caracteres!Por exemplo, em BIG5-HKSCS, como usado por exemplo na
zh_HK.big5hkscs
localidade (Hong Kong), todosĚαжふ㘘㙡䓀䨵䪤么佢俞偅傜兝功吒吭园坼垥塿墦声娉娖娫嫹嬞孀尐岤崤幋廄惝愧揊擺暝枯柦槙檝歿汻沔涂淚滜潿瀙瀵焮燡牾狖獦珢珮琵璞疱癧礒稞穀笋箤糭綅縷罡胐胬脪苒茻莍蓋蔌蕚螏螰許豹贕赨跚踊蹾躡鄃酀酅醆鈾鎪閱鞸餐餤駹騱髏髢髿鱋鱭黠﹏?????????
contêm o byte 0x5c (que também é a codificação de\
).Com a maioria das
printf
implementações, nesse locale,printf 'αb'
não produzαb
mas byte0xa3
(o primeiro byte da codificação deα
) seguido pelo caractere BS (a expansão de\b
).O melhor é evitar usar (e até instalar / disponibilizar) esses locais, pois eles causam todos os tipos de bugs e vulnerabilidades desse tipo.
Algumas
printf
implementações oferecem suporte a opções, e mesmo aquelas que não são necessárias para oferecer suporte--
como delimitador de opção. Portantoprintf --
, não produzirá,--
mas provavelmente relatará um erro sobre um argumento de formato ausente. Então, se você não pode garantir que seu formato não começará com-
, você deve usar o--
delimitador de opções:De qualquer forma, se você quiser imprimir strings arbitrárias, você usaria:
Não há nenhum caractere especial na string passada para
%s
(embora observe que, com exceção doprintf
embutido dezsh
, você não pode passar o caractere NUL em nenhum dosprintf
argumentos).Observe que, embora a maneira canônica de inserir um literal
\
seja com\\
e um literal%
com%%
, em sistemas baseados em ASCII, você também pode usar\134
e\45
e com algumasprintf
implementações\x5c
,\x25
, ou\x{5c}
,\x{25}
, ou (mesmo em sistemas não ASCII):\u005c
,\u0025
ou\u{5c}
,\u{25}
.¹
yash
éprintf
a única exceção que conheço.Do manual:
Isso lista várias sequências interpretadas. A seguir estão aqueles em que o próprio caractere precisa ser escapado.
Testei esses três no
bash
, e eles se comportaram conforme o esperado. De acordoman bash
com , esta implementação deprintf
usa as "especificações de formato printf(1) padrão" como acima, além de algumas outras que não são relevantes aqui.No entanto, outros shells, como
zsh
implementamprintf
um pouco diferente. Aqui, as aspas duplas não devem ser escapadas.