Mnoho otázek, jako je „Jak napsat znak dvojitých uvozovek (“)?‘, se ptáme, a my nechceme zahlcovat naši komunitu stejnou odpovědí (Zadejte to jako
"
pokud není uzavřeno v'
s,"
pokud je uzavřen v'
s.) Takže otázka je zde.
Do terminálu nemůžete zadávat speciální znaky jako normální, např. tento příkaz selže:
echo Updates (11)
Jak tedy zadat tyto znaky do terminálu, jako by to byly normální?
!#$^&*?[](){}<>~;'"|<space><tab><newline>
Přijatá odpověď:
To hodně záleží na skořápce. Podrobnosti najdete v příručce k shellu.
Všimněte si také, že některé znaky jsou speciální pouze v některých kontextech. Například ve většině shellů *
a ?
jsou speciální pouze v kontextech seznamu,
v shellech POSIX nebo csh, ~
je speciální pouze na začátku slova nebo po některých znacích jako :
. Totéž pro =
v zsh
. V některých prostředích [
je speciální pouze tehdy, když je (s určitými omezeními) shodný s ]
.
V některých shellech, jako je bash
nebo yash
, speciální znaky, jako jsou prázdné oddělovače tokenů, se také liší podle národního prostředí.
Operátory uvozovek (k odstranění speciálního významu těchto znaků) se také mezi shelly velmi liší.
Skořápky podobné Bourne
Shrnutí pro shelly podobné Bourneovi (to jsou shelly, o kterých je známo, že se nazývají sh
na nějakém systému nebo jiném od 80. let):
Bourne shell
Speciální znaky:
"'&|;()^`<>$
, mezera, nový řádek a tabulátor jsou speciální v jednoduchých příkazových řádcích, pokud nejsou v uvozovkách.#
(kromě dřívější verze) je speciální na začátku řádku nebo za mezerou bez uvozovek, tabulátorem nebo&|()^<>;`
.{
a}
jsou speciální pouze v tom, že se jedná o klíčová slova shellu (tedy pouze slova na pozici příkazu).*?[
jsou speciální jako globbing operátory, takže pouze v kontextu seznamu. V případě[
, je to[...]
to je globbing operátor, buď[
nebo]
stačí pouze citovat, aby se odstranil zvláštní význam.=
je speciální v kontextech, kde se s ním zachází jako s operátorem přiřazení. Tedy v jednoduchém příkazu pro všechna slova, která nenásledují argument (kromě poset -k
).
Citování operátorů
{
uvozuje všechny speciální znaky kromě nového řádku (<newline>
je způsob, jak pokračovat v dlouhém logickém řádek na další fyzický řádek, takže sekvence je odstraněna). Všimněte si, že backticks přidávají další složitost jako v nich,{
se používá jako první k opuštění uzavíracího zpětného znaménka a pomáhá analyzátoru. Uvnitř dvojitých uvozovek{
lze použít pouze k escapování samotného, "
,$
a`
(<newline>
je stále pokračováním linky). Uvnitř dokumentu zde, stejné kromě"
.{
je jediný způsob, jak uniknout znakům v těchto dokumentech."..."
dvojité uvozovky uvozují všechny znaky kromě samotného{
,$
a`
.'...'
jednoduché uvozovky unikají všem znakům kromě něj samotného.
Skořápky POSIX
Shelly POSIX se chovají většinou jako Bourne shell, kromě toho:
^
již není speciální znak~
je v některých kontextech zvláštní{
je povoleno být speciální, takže by mělo být citováno.
ksh
jako POSIX kromě toho:
{string}
je speciální, pokud řetězec obsahuje,
bez uvozovek (nebo..
v některých případech au některých verzí).- ksh93 má další speciální operátor uvozovek:
$'...'
se složitými pravidly. Tento operátor se také nachází (s určitými obměnami) vbash
,zsh
,mksh
a FreeBSD a busyboxsh
. ksh93
má také$"..."
operátor citací, který funguje jako"..."
kromě toho, že řetězec podléhá lokalizaci (lze nakonfigurovat tak, aby se překládal do jazyka uživatele).mksh
ignoruje$
v$"..."
.- od
ksh93r
,ksh93
podporuje styl csh (ve výchozím nastavení není povoleno) s-H
/-o histexpand
v interaktivních shellech), což vytváří^
na začátku příkazů a!
speciální.!
je pak v některých kontextech zvláštní (nikoli, když následuje mezera nebo TAB, ani v těchto dokumentech) a není uvozován dvojitými uvozovkami. Uniknou pouze zpětné lomítko (nikoli v uvozovkách) a jednoduché uvozovky.
bash
jako ksh93
ale:
- v jednobajtových znakových národních prostředích, vše prázdné (podle národního prostředí) znaky jsou považovány za oddělovače (jako mezera nebo tabulátor). Ve skutečnosti to znamená, že byste měli citovat všechny bajty s nastaveným 8. bitem pro případ, že by v některém národním prostředí mohl být prázdný znak.
- Rozšíření historie csh je v interaktivních instancích ve výchozím nastavení povoleno, se stejnými poznámkami jako u ksh93 výše kromě toho, že v novějších verzích
bash
,!
také někdy není zvláštní, když následuje"
.
zsh
jako ksh93
ale:
- stejná poznámka jako pro
bash
pro rozšíření historie csh =
je speciální jako první znak slova (=ls
expanduje na/bin/ls
).{
a}
může také otevírat a zavírat skupiny příkazů, pokud nejsou odděleny (jako v{echo text}
funguje jako Bourneův{ echo text;}
).- kromě
[
sám,[
potřeby jsou uvedeny, i když nejsou uzavřeny]
. - S
extendedglob
možnost povolena,#
,^
a~
jsou globální operátoři. - Pomocí
braceccl
možnost,{non-empty-string}
je speciální. $"..."
není podporováno.- jako zvláštní vtip,
?
není zvláštní při sledování%
(i v uvozovkách nebo rozšířených) na začátku slova (aby byl povolen%?name
specifikace práce) - a
rcquotes
možnost (ve výchozím nastavení není povolena) umožňuje zadat jednoduché uvozovky jako''
uvnitř jednoduchých uvozovek à larc
(viz níže).
yash
jako POSIX
kromě toho.
- všechny prázdné znaky jsou považovány za oddělovače.
- Pomocí
brace-expand
implementuje rozšíření složené závorky ve stylu zsh.
Pro všechny shelly existují některé speciální kontexty, kde citace fungují odlišně. Již jsme zde zmínili dokumenty a zpětná označení, ale je zde také [[...]]
v ksh a několika dalších shellech, POSIX $((...))
, case
konstrukce…
Všimněte si také, že citace mohou mít další vedlejší účinky, pokud jde o rozšíření (s dvojitými uvozovkami) nebo při použití zde oddělovačů dokumentu. Také zakáže vyhrazená slova a ovlivní rozšíření aliasů.
Shrnutí
Ve skořápkách podobných Bourneovi !#$^&*?[(){}<>~;'"`|=
, SPC, TAB, NEWLINE a některé bajty s nastaveným 8. bitem jsou nebo mohou být speciální (alespoň v některých kontextech).
Chcete-li odstranit zvláštní význam, aby se s nimi zacházelo doslovně, použijte uvozovky.
Použijte:
-
'...'
pro odstranění speciálního významu každého znaku:printf '%sn' '// Those $quoted$ strings are passed literally as single arguments (without the enclosing quotes) to `printf`'
-
{
pro odstranění speciálního významu pouze jednoho znaku:printf '<%s>n' foo bar baz #comment
Výše pouze znak mezery, kterému předchází
{
je předán doslovaprintf
. S těmi ostatními zachází shell jako s oddělovači tokenů. -
použijte
"..."
citovat znaky a přitom stále povolit rozšíření parametrů ($var
,$#
,${foo#bar}
…), aritmetické rozšíření ($((1+1))
, také$[1+1]
v některých shellech) a záměna příkazů ($(...)
nebo starý tvar`...`
. Ve skutečnosti většinu času v každém případě chcete umístit tato rozšíření do dvojitých uvozovek. Můžete použít{
v rámci"..."
k odstranění speciálního významu znaků, které jsou stále speciální (ale pouze ony). -
pokud řetězec obsahuje
'
znak, stále můžete použít'...'
pro zbytek a použijte jiné citační mechanismy, které umí citovat'
jako"'"
nebo'
nebo (je-li k dispozici)$'''
:echo 'This is "tricky", isn'''t it?'
-
Použijte moderní
$(...)
forma substituce příkazů. Používejte pouze staré`...`
kvůli kompatibilitě s Bourne shellem, tedy velmi starým systémem, a pouze v přiřazení proměnných, jako v případě nepoužívejte:echo "`echo "foo bar"`"
Což nebude fungovat s Bourne shell nebo AT&T verzemi ksh. Nebo:
echo "`echo "foo bar"`"
Což bude fungovat s Bourne a AT&T ksh, ale ne s
yash
(Úprava 2020: pouze ve verzi 2.41 a dřívějších, od té doby bylo změněno ve 2.42 / hlášení o chybě / odevzdání), ale použijte:var=`echo "foo bar"`; echo "$var"
který bude fungovat se všemi.
Vnořit je přenosně s dvojitými uvozovkami je také nemožné, takže znovu použijte proměnné. Pozor také na speciální zpracování zpětného lomítka:
var=`printf '%sn' '\'`
Uloží pouze jedno zpětné lomítko do
$var
, protože existuje další úroveň zpracování zpětného lomítka (pro{
, ` a$
(a také"
v uvozovkách kroměyash
)) v rámci backticks, takže potřebujete buďvar=`printf '%sn' '\\'`
nebo
var=`printf '%sn' '\'
místo toho.
Rodina Csh
csh a tcsh mají výrazně odlišnou syntaxi, i když s Bourne shellem mají stále mnoho společného, protože sdílejí společné dědictví.
Speciální znaky:
"'&|;()^`<>$
, mezera, nový řádek a tabulátor jsou speciální všude, když nejsou v uvozovkách.#
(csh je shell, který zavedl#
jako hlavní komentář) je zvláštní na začátku skriptu nebo po mezerě, tabulátoru nebo novém řádku bez uvozovek.*?[
jsou speciální jako globbing operátory, takže v kontextu seznamu{non-empty-string}
je speciální (csh je shell, který zavedl expanzi rovnátka).!
a^
jsou speciální jako součást expanze historie (opět vynález csh) a pravidla pro citování jsou speciální.~
(expanze tildy také vynález csh) je v některých kontextech zvláštní.
Citování operátorů
Jsou stejné jako u Bourne shellu, ale chování se liší. tcsh se z hlediska syntaxe chová jako csh, zjistíte, že mnoho verzí csh má ošklivé chyby. Získejte nejnovější verzi tcsh a získejte zhruba funkční verzi csh.
{
escapuje jeden znak kromě nového řádku (stejné jako u Bourne shellu). Je to jediný operátor uvozovek, který může uniknout!
.<newline>
neunikne, ale převede jej z oddělovače příkazů na oddělovač tokenů (jako mezera)"..."
escapuje všechny znaky kromě sebe sama,$
,`
, nový řádek a!
. Na rozdíl od Bourne shellu nemůžete použít{
pro únik$
a`
uvnitř"..."
, ale můžete použít{
uniknout!
nebo nový řádek (ale ne sám, kromě případů, kdy je před!
nebo nový řádek). Doslovné!
je"!"
a doslovný!
je"\!"
.'...'
escapuje všechny znaky kromě sebe sama,!
a nový řádek. Podobně jako u dvojitých uvozovek!
a nový řádek lze escapovat zpětným lomítkem.- Náhrada příkazu je pouze prostřednictvím
`...`
syntaxe a nelze je spolehlivě používat. - variabilní substituce je také dost špatně navržená a náchylná k chybám. A
$var:q
operátor pomáhá psát spolehlivější kód zahrnující proměnné.
Shrnutí
Pokud můžete, držte se dál od csh. Pokud nemůžete použít:
- jednoduché uvozovky pro citaci většiny znaků.
!
a nový řádek stále potřebují{
. {
může uniknout většině postav"..."
mohou v něm povolit některá rozšíření, ale to je docela bug, pokud vkládají znaky nového řádku a/nebo zpětného lomítka, nejlepší může být použít pouze jednoduché uvozovky a$var:q
pro variabilní expanzi. Pokud chcete spolehlivě spojovat prvky pole, budete muset používat smyčky.
rc
rodina
rc
je plan9
shell a jako jeho potomci es
a akanga
byl portován na Unix a unixové systémy. To je shell s mnohem čistší a lepší syntaxí, který by každý používal, kdybychom nezůstali u Bourneových shellů kvůli zpětné kompatibilitě.
rc
/akanga
Speciální znaky
#;&|^$=`'{}()<>
, SPC, TAB a NEWLINE jsou vždy speciální, pokud nejsou uvedeny.*?[
jsou globální operátoři.
Citující operátor
'...'
je jediným citujícím operátorem. Doslovný '
se zapisuje pomocí ''
v jednoduchých uvozovkách jako v:
echo 'it''s so simple isn''t it?'
es
es
lze považovat za experimentální shell založený na rc
.
Má to však několik rozdílů. Jedna zajímavá pro tuto Q/A je {
je také operátor uvozovek (který uvádí všechny speciální znaky kromě nového řádku) a lze jej také použít k zavedení escape sekvencí jako n
pro nový řádek b
pro zpětné lomítko…
ryby
fish je relativní novinkou (kolem roku 2005), je primárně určena pro interaktivní použití a má také výrazně odlišnou syntaxi od ostatních skořápek.
zvláštní znaky
"'()$%{}^<>;&|
vždy zvláštní, když není v uvozovkách (všimněte si%
(pro expanzi pid) jako významný rozdíl od ostatních shellů a`
není zvláštní)#
(komentář) speciální, pokud následuje mezera bez uvozovek, tabulátor, nový řádek nebo;&|^<>
*?
(ale ne[...]
) globbing operátory
Citování operátorů
{
uvozuje jeden speciální znak kromě nového řádku, ale dejte si pozor, funguje také jako sekvence C escape (n
,b
…) uvaděč. IOW,n
nenín
v uvozovkách ale nový řádek."..."
cituje vše kromě sebe,$
a zpětné lomítko a zpětné lomítko lze použít k tomu, aby jim uniklo.<newline>
je pokračováním řádku (odstraněno) uvnitř"..."
.'...'
cituje vše kromě sebe sama a{
a můžete je použít zpětné lomítko.