Como escapar caracteres especiais em uma string?

15

Supondo que $file tenha um valor de nome de arquivo, digamos Dr' A.tif . Na programação bash, como eu poderia escapar aspas simples e qualquer outro caractere especial do $file sem remover o caractere especial?

Atualização em 9 de julho de 2014

Como solicitação do @Gilles Dr' A.tif :

files=$(find /path/ -maxdepth 1 -name "*.[Pp][Dd][Ff]" -o -name "*.[Tt][Ii][Ff]")
echo "${files}" > ${TEMP_FILE}
while read file
do
   newfile=$(echo "${file}" | sed 's, ,\ ,g') ## line 1
done < ${TEMP_FILE}

Depois de testar a resposta do @Patrick no line 1 , parece funcionar para mim . Mas se eu tiver arquivos como Dr\^s A.tif , o comando printf não parece ajudar, isso me mostra Dr\^s\ A.tif . Se eu tentar manualmente no console assim:

printf "%q" "Dr\^s A.tif"

Eu terei esta saída:

Dr\\^s\ A.tif

Alguma ideia de como lidar com isso?

    
por huahsin68 08.07.2014 / 12:44

5 respostas

11

Você pode usar o printf incorporado com %q para fazer isso. Por exemplo:

$ file="Dr' A.tif"
$ printf '%q\n' "$file"
Dr\'\ A.tif

$ file=' foo$bar\baz''
$ printf '%q\n' "$file"
\ foo\$bar\baz\'

Da documentação bash em printf :

In addition to the standard format specifications described in printf(1)
and printf(3), printf interprets:

 %b       expand backslash escape sequences in the corresponding argument
 %q       quote the argument in a way that can be reused as shell input
 %(fmt)T  output the date-time string resulting from using FMT as a format
          string for strftime(3)
    
por 08.07.2014 / 14:15
4

Tente: -

file=Dr\'\ A.tif
echo $file
Dr' A.tif

ou

file="Dr' A.tif"
echo $file
Dr' A.tif

ou se a string contiver uma aspa dupla: -

file='Dr" A.tif'
echo $file
Dr" A.tif

Existem bons tutoriais sobre como escapar e citar na rede. Comece com este .

    
por 08.07.2014 / 12:54
1

Você não precisa escapar de nenhum nome de arquivo que esteja manipulando em um script. Escapar é necessário apenas se você quiser colocar um nome de arquivo como um literal em um script, ou passar vários nomes de arquivo como um único fluxo de entrada para outro script.

Como você está circulando pela saída de find , isso é uma das maneiras mais simples (!) de lidar com todos os caminhos possíveis :

while IFS= read -r -d ''
do
    file_namex="$(basename -- "$REPLY"; echo x)"
    file_name="${file_namex%$'\nx'}"
    do_something -- "$file_name"
done <(find "$some_path" -exec printf '%s
while IFS= read -r -d ''
do
    file_namex="$(basename -- "$REPLY"; echo x)"
    file_name="${file_namex%$'\nx'}"
    do_something -- "$file_name"
done <(find "$some_path" -exec printf '%s%pre%' {} +)
' {} +)
    
por 08.07.2014 / 14:09
0

rápido e (muito) sujo

find . | sed 's/^/"/' | sed 's/$/"/'
    
por 25.04.2015 / 01:37
-1

Muitas dessas respostas, incluindo a mais votada usando printf "%q" , não funcionarão em todos os casos sem manipulação adicional. Eu sugeriria o seguinte (exemplo abaixo):

cat <<EOF; 2015-11-07T03:34:41Z app[postgres.0000]: [TAG] text-search query doesn't contain lexemes: "" EOF

    
por 07.11.2015 / 07:07

Tags