Bash'te, bir komuta komut satırı bağımsız değişkenleri belirtirken, hangi karakterlerin kaçması gerekir?
Onlar Bash meta karakterlere sınırlıdır: Boşluk, sekme,
|
, &
, ;
, (
, )
, <
, ve >
?
Bash'te, bir komuta komut satırı bağımsız değişkenleri belirtirken, hangi karakterlerin kaçması gerekir?
Onlar Bash meta karakterlere sınırlıdır: Boşluk, sekme,
|
, &
, ;
, (
, )
, <
, ve >
?
Yanıtlar:
Aşağıdaki karakterlerin bazı bağlamlarda kabuğun kendisi için özel bir anlamı vardır ve bağımsız değişkenlerden kaçmaları gerekebilir:
`
Backtick (U + 0060 Mezar Vurgusu)~
Tilde (U + 007E)!
Ünlem işareti (U + 0021)#
Hash (U + 0023 Sayı İşareti)$
Dolar işareti (U + 0024)&
Ve işareti (U + 0026)*
Yıldız işareti (U + 002A)(
Sol Parantez (U + 0028))
Sağ parantez (U + 0029)
( ⇥
) Sekme (U + 0009){
Sol destek (U + 007B Sol Kıvırcık Parantez)[
Sol köşeli ayraç (U + 005B)|
Dikey çubuk (U + 007C Dikey Çizgi)\
Ters Eğik Çizgi (U + 005C Ters Solidus);
Noktalı virgül (U + 003B)'
Tek Alıntı / Kesme İşareti (U + 0027)"
Çift tırnak (U + 0022)↩
Yeni hat (U + 000A)<
Küçüktür (U + 003C)>
Büyüktür (U + 003E)?
Soru işareti (U + 003F)
Boşluk (U + 0020) 1Bu karakterlerden bazıları, bağladığım karakterden daha fazla şey ve daha fazla yerde kullanılıyor.
Açıkça isteğe bağlı birkaç köşe örneği vardır:
!
set +H
etkileşimli olmayan kabuklarda varsayılan olan devre dışı bırakılabilir .{
ile devre dışı bırakılabilir set +B
.*
ve ?
ile devre dışı bırakılabilir set -f
veyaset -o noglob
.=
Eşittir işaretinin (U + 003D) set -k
veyaset -o keyword
etkinleştirilirse de kaçması gerekir .Yeni satırdan kaçmak alıntı yapmak gerektirir - ters eğik çizgiler işi yapmaz. IFS'de listelenen diğer karakterlerin de benzer şekilde ele alınması gerekir. Kaçmak gerek yok ]
ya }
, ama do kaçmak gerekir )
bir operatör olduğu için.
Bu karakterlerden bazıları, kaçmak gerektiğinde diğerlerinden daha sıkı sınırlara sahiptir. Örneğin a#b
, tamam, ama a #b
bir açıklama, >
her iki bağlamda kaçmak gerekir. Zaten hepsinden muhafazakar bir şekilde kaçmak acı vermez ve ince ayrımları hatırlamaktan daha kolaydır.
Komut adınızın kendisi bir kabuk anahtar kelimesi ( ,, ) if
ise for
, do
sizden de kaçmanız veya alıntı yapmanız gerekir. Bunlardan tek ilginç olanı, in
bunun her zaman bir anahtar kelime olduğu açık değildir. Sen yok (! Aptalca) yalnızca olmasa da bunu, argümanları kullanılan anahtar kelimeler için bunu yapmak zorunda Bunlardan birinin peşine bir komut adını verdi. Kabuk operatörleri ( (
, &
vb.) Her zaman nerede olurlarsa olsun alıntı yapmaya ihtiyaç duyarlar.
1 Stéphane, bölgenizdeki herhangi bir tek baytlık boş karakterin de kaçması gerektiğini belirtti. En yaygın, mantıklı yerel ayarlarda, en azından C veya UTF-8 tabanlı olanlarda, yalnızca yukarıdaki boşluk karakteridir. Bazı ISO-8859-1 yerlerinde, Solaris, BSD'ler ve OS X dahil olmak üzere U + 00A0 kesintisiz alan boş kabul edilir (Yanlış düşünüyorum). Rastgele bilinmeyen bir yerle uğraşıyorsanız, harfler de dahil olmak üzere hemen hemen her şeyi içerebilir, iyi şanslar.
Muhtemelen, boş olmayan çok baytlık bir karakter içinde boş olarak kabul edilen tek bir bayt görünebilir ve her şeyi tırnak içine almaktan başka bir şeyden kaçamazsınız. Bu teorik bir endişe değildir: yukarıdan ISO-8859-1 yerel ayarında, A0
boş olarak kabul edilen bayt, UTF-8 kodlu "à" ( ) gibi çok baytlı karakterler içinde görünebilir C3 A0
. Bu karakterleri güvenli bir şekilde ele almak için onları alıntılamanız gerekir "à"
. Bu davranış, komut dosyasını yazdığınız ortamdaki yerel ayarlara bağlıdır; yazdığınız kod değil.
Bence bu davranış birden çok yönden kırıldı, ama ele aldığımız eli oynamak zorundayız. Kendiliğinden senkronize olmayan çok baytlı karakter kümeleriyle çalışıyorsanız, en güvenli şey her şeyi alıntılamak olacaktır. UTF-8 veya C'deyseniz (şimdilik) güvendesiniz.
!
komut dosyalarında değil, yalnızca csh geçmişi genişletmesi etkinleştirildiğinde kaçmanız gerekir . [ ! -f a ]
ya find . ! -name...
da iyi. Bu, daha sıkı sınırlar bölümünüz tarafından kapsanır, ancak açıkça belirtmeye değer.
hash[foo"]"]=
, ${var-foo"}"}
, [[ "!" = b ]]
, [[ a = "]]" ]]
, için regexp operatörleri [[ x =~ ".+[" ]]
. Dışında anahtar kelimeler {
( if
, while
, for
bunlar gibi tanınmış değiliz yani ...) ... alıntı gerekecektir
]
), bu yüzden onları listelemiyorum. Herhangi bir anahtar kelimenin bağımsız değişken konumunda alıntı yapması gerektiğini düşünmüyorum.
GNU Paralel'de bu test edilir ve kapsamlı olarak kullanılır:
$a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go;
# quote newline as '\n'
$a =~ s/[\n]/'\n'/go;
Bu test edilir bash
, dash
, ash
, ksh
, zsh
, ve fish
. Karakterlerin bazılarının kabukların bazılarında (versiyonlarında) alıntı yapmasına gerek yoktur, ancak yukarıdakiler test edilen tüm kabuklarda çalışır.
Sadece bir dize alıntı yapmak istiyorsanız, onu içine boru olabilir parallel --shellquote
:
printf "&*\t*!" | parallel --shellquote
Perl'de hafif kaçan çözüm için, tek tırnak prensibini takip ediyorum. Tek tırnak içindeki bir Bash-string, tek tırnak dışında herhangi bir karakter içerebilir.
Kodum:
my $bash_reserved_characters_re = qr([ !"#$&'()*;<>?\[\\`{|~\t\n]);
while(<>) {
if (/$bash_reserved_characters_re/) {
my $quoted = s/'/'"'"'/gr;
print "'$quoted'";
} else {
print $_;
}
}
Örnek çalışma 1:
$ echo -n "abc" | perl escape_bash_special_chars.pl
abc
Örnek çalışma 2:
echo "abc" | perl escape_bash_special_chars.pl
'abc
'
Örnek çalışma 3:
echo -n 'ab^c' | perl escape_bash_special_chars.pl
ab^c
Örnek çalışma 4:
echo -n 'ab~c' | perl escape_bash_special_chars.pl
'ab~c'
Örnek çalışma 5:
echo -n "ab'c" | perl escape_bash_special_chars.pl
'ab'"'"'c'
echo 'ab'"'"'c'
ab'c