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ší manipulaceIt 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 byloread -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.