Come sfuggire a caratteri speciali in una stringa?


16

Supponendo che $filedetenga un valore di un nome file, diciamo Dr' A.tif. Nella programmazione bash, come potrei evitare la virgoletta singola e qualsiasi altro carattere speciale $filesenza rimuovere il carattere speciale?

Aggiornamento del 9 luglio 2014

Come richiesto da @Gilles , il seguente frammento di codice che non è in grado di gestire 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}

Dopo aver provato la risposta da @Patrick in poi line 1, sembra funzionare per me. Ma se ho file come Dr\^s A.tif, il printfcomando non sembra aiutare, mi mostra Dr\^s\ A.tif. Se lo provo manualmente su console in questo modo:

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

Avrò questo output:

Dr\\\^s\ A.tif

Qualche idea su come gestirlo?


3
in quale contesto ti aspetti di utilizzare $ file? o questo problema sta assegnando la stringa con il carattere speciale a $ file?
rapina l'

In realtà il comando find mi restituisce una matrice di elenco di file. E poi faccio scorrere questo elenco di file nella variabile $ file.
huahsin68,

2
Ti sono state date alcune risposte corrette qui, ma probabilmente non sono le risposte alla domanda che stai davvero facendo. Dal tuo commento qui, sospetto fortemente che tu sia sulla strada sbagliata. Non possiamo aiutarti molto perché continui a non mostrare il tuo codice. Vi consiglio comunque di leggere Perché il mio script shell si soffoca su spazi bianchi o altri caratteri speciali? come sfondo. Mostra la tua sceneggiatura e spiega cosa vuoi fare.
Gilles 'SO- smetti di essere malvagio' l'

Risposte:


14

È possibile utilizzare il printfbuiltin con %qper ottenere questo risultato. Per esempio:

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

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

Dalla documentazione di bash su 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)

Questo non funziona con alcuni casi .eg quando è necessario conservare le virgolette doppie.
user3467349

@ user3467349 funziona perfettamente con le virgolette. Scommetto che stai provando qualcosa del genere printf '%s' "foo". È necessario capire prima come funziona l'analisi dell'argomento nella shell. Vedi gnu.org/software/bash/manual/bash.html#Shell-Operation # 2 avviene prima di # 6.
Patrick,

Potresti fornire un esempio di questa stringa stampata con printfe senza altre manipolazioniIt doesn't have a: ""
user3467349

Il tuo problema non ha nulla a che fare con printf. Il tuo problema è che non vuoi che la shell analizzi la tua stringa. Per fare ciò, devi passare il tuo input alla shell in un modo in cui non provi nemmeno ad analizzarlo. Un modo per farlo sarebbe read -r -p 'input: ' && printf '%q\n' "$REPLY"e fornire l'input quando richiesto.
Patrick,

1
Come ho già detto più volte. Non sapere come trasferire dati grezzi alla shell non è un problema printf. Forse dovresti porre una domanda piuttosto che criticare una soluzione che non ha nulla a che fare con il tuo problema.
Patrick,

4

Provare:-

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

o

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

o se la stringa contiene una doppia virgoletta: -

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

Esistono buoni tutorial su come fuggire e quotare in rete. Inizia con questo .


1

Non è necessario sfuggire ai nomi di file che si stanno gestendo in uno script. L'escaping è necessario solo se si desidera inserire un nome file come letterale in uno script o passare più nomi file come flusso di input singolo a un altro script.

Dato che stai eseguendo il loop dell'output di find, questo è uno dei modi più semplici (!) Per gestire ogni possibile percorso :

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\0' {} +)

0

veloce e (molto) sporco

find . | sed 's/^/"/' | sed 's/$/"/'

-1

Molte di queste risposte, inclusa quella più votata printf "%q", non funzioneranno in tutti i casi senza ulteriori manipolazioni. Suggerirei quanto segue (esempio di seguito):

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


Scusa la domanda n00b, ma puoi approfondire come la utilizzeresti per sfuggire ai caratteri in una stringa? Se copio il codice che scrivi nel mio terminale, stampa solo l'11 / 2015 / 2015T03: 34: 41Z app [postgres.0000]: [TAG] la query di ricerca di testo non contiene i lessemi: "" ... non viene salvato nulla .
SharkAlley,

Questo è letteralmente il punto, tutti i caratteri speciali sono interpretati come caratteri letterali non per il loro significato speciale. Prova invece a ripetere "la stringa sopra" per vedere la differenza.
user3467349
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.