Jak uniknout speciálním znakům v řetězci?

Za předpokladu, že $file drží hodnotu názvu souboru, řekněme Dr" A.tif. Jak mohu v bashovém programování uniknout jednoduché uvozovce a jakémukoli jinému speciálnímu znaku $file bez odebrání speciálního znaku?

Aktualizace dne 9. července 2014

Jako žádost od @Gilles , následující fragment kódu, který nedokáže zpracovat 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} 

Poté, co jsem vyzkoušel odpověď od @Patrick na line 1, zdá se, že funguje pro mě. Pokud však mám soubor jako Dr\^s A.tif, printf příkaz nevypadá jako pomoc, zobrazí mi Dr\^s\ A.tif. Pokud to zkusím ručně na konzole takto:

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

Budu mít tento výstup:

Dr\\\^s\ A.tif

Máte nějaký nápad, jak to vyřešit?

Komentáře

  • v čem kontextu očekáváte použití souboru $? nebo je tímto problémem přiřazení řetězce se zvláštním znakem souboru $?
  • Ve skutečnosti mi příkaz find vrátí pole seznamu souborů. A pak procházím tento seznam souborů do proměnné $ file.
  • Dostali jste zde

několik správných odpovědí, ale pravděpodobně to nejsou odpovědi na otázka, na kterou se ' opravdu ptáte. Z vašeho komentáře zde silně tuším, že jste ' na špatné cestě. ' Nemůžeme vám moc pomoci, protože svůj kód stále nezobrazujete. Doporučuji vám však přečíst Proč se můj shell skript dusí mezerami nebo jinými speciálními znaky? jako pozadí. Ukažte svůj skript a vysvětlete, co chcete dělat.

Odpovědět

Vy k dosažení tohoto cíle může použít printf zabudovaný do %q. Například:

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

Z bash dokumentace k 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) 

komentáře

  • toto nepracuje ' s určitými případy .eg když potřebujete zachovat uvozovky.
  • @ user3467349, s uvozovkami to funguje dobře. ' vsadím, že ' zkouším něco jako printf '%s' "foo". Nejprve musíte pochopit, jak syntaktická analýza argumentů funguje v shellu. Viz gnu.org/software/bash/manual/bash.html#Shell-Operation # 2 se stane před 6. #
  • Mohli byste uveďte příklad tohoto řetězce vytištěného pomocí printf a žádné další manipulace It doesn't have a: ""
  • Váš problém nemá nic společného s printf. Problém je v tom, že ' nechcete, aby shell analyzoval váš řetězec. Abyste to mohli udělat, musíte svůj vstup předat shellu tak, aby se ho ' ani nepokoušel analyzovat. Jedním ze způsobů, jak to udělat, by bylo read -r -p 'input: ' && printf '%q\n' "$REPLY" a po vyzvání poskytněte vstup.
  • Jak jsem řekl ' hned několikrát. Nevím, jak předat nezpracovaná data do shellu, není ' problém s printf. Možná byste měli položit otázku, než kritizovat řešení, které nemá nic společného s vaším problémem.

Odpověď

Vyzkoušejte: –

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

nebo

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

nebo pokud řetězec obsahuje dvojitý citát: –

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

Existují dobré návody na únik a citování na internetu. Začněte tímto .

Odpovědět

Nemáte „Není třeba uniknout ze všech názvů souborů, které ve skriptu zpracováváte. Únik je nezbytný, pouze pokud chcete ve skriptu zadat název souboru jako literál nebo předat několik názvů souborů jako jeden vstupní proud do jiného skriptu.

Protože procházíte výstupem find, tohoto je jedním z nejjednodušších způsobů (!) zvládnout všechny možné cesty :

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

Odpovědět

rychle a (velmi) špinavě

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

Odpověď

Mnoho z těchto odpovědí, včetně nejlépe hlasovaných, pomocí printf "%q" bude nefunguje ve všech případech bez další manipulace.Navrhuji následující (níže uvedený příklad):

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

Komentáře

  • Omluvte otázku n00b, ale můžete vysvětlit, jak byste to vlastně použili k úniku znaků v řetězci? Pokud zkopíruji kód, který napíšete, do svého terminálu, vytiskne se pouze aplikace 2015-11-07T03: 34: 41Z [postgres.0000]: [TAG] textový vyhledávací dotaz ' t obsahovat lexémy: " " … nic neunikne.
  • To ' S doslova bod, všechny speciální znaky jsou interpretovány jako doslovné znaky, nikoli pro jejich speciální význam. Zkuste místo toho ozvěnu " výše uvedeného řetězce " vidět rozdíl.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *