Cum să scapi de caractere speciale dintr-un șir?

Presupunând $file care deține o valoare a unui nume de fișier, spuneți Dr" A.tif. În programarea bash, cum aș putea scăpa citatul unic și orice alt caracter special al $file fără a elimina caracterul special?

Actualizare la 9 iulie 2014

Ca cerere de la @Gilles , următorul fragment de cod care nu este capabil să gestioneze 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} 

După ce am încercat răspuns de la @Patrick pe line 1, pare să funcționeze pentru mine. Dar dacă am fișier precum , comanda printf nu pare ajutor, îmi arată Dr\^s\ A.tif. Dacă îl încerc manual pe consolă astfel:

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

Voi avea această ieșire:

Dr\\\^s\ A.tif

Ai vreo idee despre cum să rezolvi acest lucru?

Comentarii

  • în ce context așteptați să utilizați fișierul $? sau această problemă este atribuirea șirului cu caracterul special la $ file?
  • De fapt, comanda find îmi returnează o serie de liste de fișiere. Și apoi parcurg această listă de fișiere în variabila $ file.
  • Ți s-au dat ' câteva răspunsuri corecte aici, dar probabil că nu sunt răspunsurile la întrebare pe care ' o întrebați cu adevărat. Din comentariul dvs. de aici, banuiesc cu tărie că ' sunteți pe un drum greșit. Nu vă putem ' să vă ajutăm mult, deoarece nu vă afișați în continuare codul. Cu toate acestea, vă recomand să citiți De ce scriptul meu shell se sufocă în spații albe sau alte caractere speciale? ca fundal. Arată-ți scriptul și explică ce vrei să faci.

Răspunde

Tu poate utiliza printf integrat cu %q pentru a realiza acest lucru. De exemplu:

$ file="Dr" A.tif" $ printf "%q\n" "$file" Dr\"\ A.tif $ file=" foo$bar\baz`" $ printf "%q\n" "$file" \ foo\$bar\\baz\` 

Din documentația bash de pe 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) 

Comentarii

  • Aceasta ' nu funcționează cu anumite cazuri .eg când trebuie să păstrați ghilimele duble.
  • @ user3467349 funcționează foarte bine cu ghilimelele. ' pariez că ' reîncerc ceva de genul printf '%s' "foo". Mai întâi trebuie să înțelegeți cum funcționează analiza argumentelor în shell. Vedeți gnu.org/software/bash/manual/bash.html#Shell-Operation # 2 se întâmplă înainte de # 6.
  • Ați putea furnizați un exemplu al acestui șir tipărit cu printf și fără alte manipulări It doesn't have a: ""
  • Problema dvs. nu are nicio legătură cu printf. Problema dvs. este că nu ' nu doriți ca shell-ul să vă analizeze șirul. Pentru a face acest lucru, trebuie să transmiteți intrarea în shell într-un mod în care nici măcar nu încearcă să-l analizeze '. O modalitate de a face acest lucru ar fi read -r -p 'input: ' && printf '%q\n' "$REPLY" și furnizarea intrării atunci când vi se solicită.
  • După cum am spus i ' de câteva ori acum. Nu știți cum să transmiteți datele brute către shell nu este ' o problemă cu printf. Poate că ar trebui să puneți o întrebare mai degrabă decât să criticați o soluție care nu are nimic de-a face cu problema dvs.

Răspuns

Încercați: –

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

sau

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

sau dacă șirul conține o dublă citat: –

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

Există tutoriale bune despre evadare și citare pe net. Începeți cu acesta .

Răspundeți

Nu „Nu trebuie să scăpați de orice nume de fișiere pe care le gestionați într-un script. Escaparea este necesară numai dacă doriți să puneți un nume de fișier ca literal într-un script sau să treceți mai multe nume de fișiere ca un singur flux de intrare într-un alt script.

Deoarece „repetați în buclă ieșirea find, acesta este una dintre cele mai simple modalități (!) de a gestiona fiecare cale posibilă :

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" {} +) 

Răspuns

rapid și (foarte) murdar

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

Răspuns

Multe dintre aceste răspunsuri, inclusiv cel mai votat folosind printf "%q" nu funcționează în toate cazurile fără manipulare suplimentară.Aș sugera următoarele (exemplu de mai jos):

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

Comentarii

  • Scuză întrebarea n00b, dar poți să detalii despre cum ai folosi de fapt acest lucru pentru a scăpa de caractere dintr-un șir? Dacă copiez codul pe care îl scrieți în terminalul meu, acesta tipărește doar 2015-11-07T03: 34: 41Z aplicația [postgres.0000]: interogarea de căutare text [TAG] nu ' conțin lexeme: " " … nu se scapă nimic.
  • Acel ' este literalmente punctul, toate caracterele speciale sunt interpretate ca caractere literale, nu pentru semnificația lor specială. Încercați să echo " șirul de mai sus " pentru a vedea diferența.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *