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ăriIt 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 firead -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.