Nie zapomnij (możliwe) globowanie nazw plików za pomocą * i?
Jeff Schaller
Dzięki. Czy możesz wyczerpująco wymienić rodzaje znaków, które muszą być poprzedzone znakami argumentów linii cmd?
Tim
Dobrze jest mieć tę listę, ale najważniejszą rzeczą do zrozumienia w cytowaniu jest: Wszystko między pojedynczymi cudzysłowami jest przekazywane dosłownie i bez podziału słów. Bez wyjątków. (Nawiasem mówiąc, oznacza to, że nie ma możliwości osadzenia pojedynczego cytatu w pojedynczych cytatach, ale łatwo to obejść .)
Wildcard
Odpowiedzi:
22
Następujące znaki mają specjalne znaczenie dla samej powłoki w niektórych kontekstach i może wymagać zmiany znaczenia w argumentach:
=Znak równości (U + 003D) również musi być uciekł jeśli set -kczyset -o keyword jest włączona.
Ucieczka od nowego wiersza wymaga cytowania - odwrotne ukośniki nie wykonają zadania. Wszelkie inne znaki wymienione w IFS będą wymagały podobnej obsługi. Nie trzeba uciekać ]albo }, ale nie trzeba uciekać ), bo to operator.
Niektóre z tych postaci mają ścisłe ograniczenia, kiedy naprawdę potrzebują ucieczki, niż inne. Na przykład a#bjest w porządku, ale a #bjest komentarzem, podczas gdy >musiałby uciekać w obu kontekstach. Zresztą nie zaszkodzi im uciec zachowawczo i jest to łatwiejsze niż zapamiętanie drobnych różnic.
Jeśli sama nazwa polecenia jest kluczowe shell ( if, for, do), a następnie będziesz musiał uciec lub zacytować go zbyt. Jedyny interesujący z nich to in, ponieważ nie jest oczywiste, że zawsze jest to słowo kluczowe. Ci nie muszą tego robić dla słów kluczowych używanych w argumentach, tylko wtedy, gdy masz (głupio!) O nazwie polecenia po jednym z nich. Operatorzy powłoki ( (, &itp.) Zawsze potrzebują cytowania, gdziekolwiek się znajdują.
1 Stéphane zauważył, że każda inna jednobajtowa pusta postać z twojego regionu również potrzebuje ucieczki. W najczęstszych, rozsądnych lokalizacjach, przynajmniej tych opartych na C lub UTF-8, są to tylko powyższe białe znaki. W niektórych lokalizacjach ISO-8859-1 przestrzeń bez przerw U + 00A0 jest uważana za pustą, w tym Solaris, BSD i OS X (myślę niepoprawnie). Jeśli masz do czynienia z dowolnym nieznanym miejscem, może ono zawierać prawie wszystko, w tym litery, więc powodzenia.
Można sobie wyobrazić, że pojedynczy bajt uważany za pusty może pojawiać się w wielobajtowym znaku, który nie był pusty, i nie byłoby sposobu, aby uciec od tego, poza umieszczeniem całego zdania w cudzysłowie. Nie jest A0to kwestia teoretyczna: w ustawieniu ISO-8859-1 z góry ten bajt, który jest uważany za pusty, może pojawiać się w znakach wielobajtowych, takich jak UTF-8 zakodowane „à” ( C3 A0). Aby bezpiecznie obchodzić się z tymi postaciami, musisz je zacytować "à". To zachowanie zależy od konfiguracji ustawień regionalnych w środowisku, w którym działa skrypt, a nie od tego, w którym został napisany.
Myślę, że to zachowanie jest zepsute na wiele sposobów, ale musimy rozgrywać rozdanie, które otrzymaliśmy. Jeśli pracujesz z dowolnym niesynchronizującym wielobajtowym zestawem znaków, najbezpieczniej byłoby zacytować wszystko. Jeśli jesteś w UTF-8 lub C, jesteś bezpieczny (na razie).
Musisz tylko uciec, !gdy włączone jest rozszerzanie historii csh, zwykle nie w skryptach. [ ! -f a ]lub find . ! -name...są w porządku. Jest to omówione w części dotyczącej bardziej rygorystycznych limitów, ale może warto o tym wyraźnie wspomnieć.
Stéphane Chazelas,
Należy pamiętać, że istnieją konteksty, w których inne postacie muszą cytowania jak: hash[foo"]"]=, ${var-foo"}"}, [[ "!" = b ]], [[ a = "]]" ]], operatorzy regexp dla [[ x =~ ".+[" ]]. Inne niż słowa kluczowe {( if, while, for...) musiałby być cytowane więc nie są one rozpoznawane jako takie ...
Stéphane Chazelas
W zakresie, w jakim w ogóle są to argumenty wiersza polecenia, interpretacja zależy od danego polecenia (podobnie jak ]), więc nie wymienię ich. Nie sądzę, aby jakieś słowo kluczowe wymagało cytowania w pozycji argumentu.
Michael Homer,
2
Cytowanie wbudowanych, myślników lub% nic nie robi.
Michael Homer
3
W GNU Parallel jest to testowane i szeroko stosowane:
Jest on testowany w bash, dash, ash, ksh, zsh, i fish. Niektóre znaki nie wymagają cytowania w niektórych (wersjach) powłok, ale powyższe działa we wszystkich testowanych powłokach.
Jeśli chcesz po prostu zacytować ciąg, możesz go potokować w parallel --shellquote:
@TomH Będziemy wdzięczni, jeśli poświęcisz 5 minut na zastanowienie się, w jaki sposób mogliśmy do ciebie dotrzeć.
Ole Tange
Myślę, że to problem z postępem. większość ludzi nie potrzebuje ani nie rozumie równolegle, dopóki nie przejdzie przez pewne etapy złożoności. Do tego czasu natknęli się na xargs, nohup i tym podobne. Nie widzę też wielu osób używających równolegle do rozwiązywania problemów w wymianie stosów lub kiedy szukam rozwiązań problemów z bashiem
Tom H
1
W przypadku lekkiego rozwiązania ucieczki w Perlu, kieruję się zasadą pojedynczych cudzysłowów. Ciąg Bash w pojedynczych cudzysłowach może mieć dowolny znak, z wyjątkiem samego pojedynczego cudzysłowu.
Mój kod:
my $bash_reserved_characters_re = qr([!"#$&'()*;<>?\[\\`{|~\t\n]);
while(<>) {
if (/$bash_reserved_characters_re/) {
my $quoted = s/'/'"'"'/gr;
print "'$quoted'";}else{
print $_;}}
Tak, ważne, że to. Moim zdaniem większość osób wyląduje na tej stronie, ponieważ mają problem do rozwiązania. Nie dlatego, że stanowi to interesującą debatę akademicką. Dlatego chciałbym oferować rozwiązania i omawiać ich zalety, nawet jeśli są nieco nie na temat.
Jari Turkia
Mój kod jest tylko implementacją odpowiedzi Michaela Homera. Nie chciałem przekazywać więcej informacji niż to, co zrobił.
Odpowiedzi:
Następujące znaki mają specjalne znaczenie dla samej powłoki w niektórych kontekstach i może wymagać zmiany znaczenia w argumentach:
`
Backtick (U + 0060 Grave Accent)~
Tylda (U + 007E)!
Wykrzyknik (U + 0021)#
Hash (znak numeryczny U + 0023)$
Znak dolara (U + 0024)&
Ampersand (U + 0026)*
Gwiazdka (U + 002A)(
Lewy nawias (U + 0028))
Prawy nawias (U + 0029)(
⇥
) Zakładka (U + 0009){
Lewy nawias klamrowy (U + 007B Lewy nawias klamrowy )[
Lewy nawias kwadratowy (U + 005B)|
Pionowy pasek (linia pionowa U + 007C)\
Odwrotny ukośnik (U + 005C do tyłu Solidus);
Średnik (U + 003B)'
Pojedynczy cytat / apostrof (U + 0027)"
Podwójny cytat (U + 0022)↩
Nowa linia (U + 000A)<
Mniej niż (U + 003C)>
Większy niż (U + 003E)?
Znak zapytania (U + 003F)Spacja (U + 0020) 1
Niektóre z tych znaków są używane do więcej rzeczy i w większej liczbie miejsc niż ta, którą połączyłem.
Istnieje kilka przypadków narożnych, które są wyraźnie opcjonalne:
!
można wyłączyć za pomocąset +H
, co jest domyślne w nieinteraktywnych powłokach.{
można wyłączyć za pomocąset +B
.*
i?
można je wyłączyć za pomocąset -f
lubset -o noglob
.=
Znak równości (U + 003D) również musi być uciekł jeśliset -k
czyset -o keyword
jest włączona.Ucieczka od nowego wiersza wymaga cytowania - odwrotne ukośniki nie wykonają zadania. Wszelkie inne znaki wymienione w IFS będą wymagały podobnej obsługi. Nie trzeba uciekać
]
albo}
, ale nie trzeba uciekać)
, bo to operator.Niektóre z tych postaci mają ścisłe ograniczenia, kiedy naprawdę potrzebują ucieczki, niż inne. Na przykład
a#b
jest w porządku, alea #b
jest komentarzem, podczas gdy>
musiałby uciekać w obu kontekstach. Zresztą nie zaszkodzi im uciec zachowawczo i jest to łatwiejsze niż zapamiętanie drobnych różnic.Jeśli sama nazwa polecenia jest kluczowe shell (
if
,for
,do
), a następnie będziesz musiał uciec lub zacytować go zbyt. Jedyny interesujący z nich toin
, ponieważ nie jest oczywiste, że zawsze jest to słowo kluczowe. Ci nie muszą tego robić dla słów kluczowych używanych w argumentach, tylko wtedy, gdy masz (głupio!) O nazwie polecenia po jednym z nich. Operatorzy powłoki ((
,&
itp.) Zawsze potrzebują cytowania, gdziekolwiek się znajdują.1 Stéphane zauważył, że każda inna jednobajtowa pusta postać z twojego regionu również potrzebuje ucieczki. W najczęstszych, rozsądnych lokalizacjach, przynajmniej tych opartych na C lub UTF-8, są to tylko powyższe białe znaki. W niektórych lokalizacjach ISO-8859-1 przestrzeń bez przerw U + 00A0 jest uważana za pustą, w tym Solaris, BSD i OS X (myślę niepoprawnie). Jeśli masz do czynienia z dowolnym nieznanym miejscem, może ono zawierać prawie wszystko, w tym litery, więc powodzenia.
Można sobie wyobrazić, że pojedynczy bajt uważany za pusty może pojawiać się w wielobajtowym znaku, który nie był pusty, i nie byłoby sposobu, aby uciec od tego, poza umieszczeniem całego zdania w cudzysłowie. Nie jest
A0
to kwestia teoretyczna: w ustawieniu ISO-8859-1 z góry ten bajt, który jest uważany za pusty, może pojawiać się w znakach wielobajtowych, takich jak UTF-8 zakodowane „à” (C3 A0
). Aby bezpiecznie obchodzić się z tymi postaciami, musisz je zacytować"à"
. To zachowanie zależy od konfiguracji ustawień regionalnych w środowisku, w którym działa skrypt, a nie od tego, w którym został napisany.Myślę, że to zachowanie jest zepsute na wiele sposobów, ale musimy rozgrywać rozdanie, które otrzymaliśmy. Jeśli pracujesz z dowolnym niesynchronizującym wielobajtowym zestawem znaków, najbezpieczniej byłoby zacytować wszystko. Jeśli jesteś w UTF-8 lub C, jesteś bezpieczny (na razie).
źródło
!
gdy włączone jest rozszerzanie historii csh, zwykle nie w skryptach.[ ! -f a ]
lubfind . ! -name...
są w porządku. Jest to omówione w części dotyczącej bardziej rygorystycznych limitów, ale może warto o tym wyraźnie wspomnieć.hash[foo"]"]=
,${var-foo"}"}
,[[ "!" = b ]]
,[[ a = "]]" ]]
, operatorzy regexp dla[[ x =~ ".+[" ]]
. Inne niż słowa kluczowe{
(if
,while
,for
...) musiałby być cytowane więc nie są one rozpoznawane jako takie ...]
), więc nie wymienię ich. Nie sądzę, aby jakieś słowo kluczowe wymagało cytowania w pozycji argumentu.W GNU Parallel jest to testowane i szeroko stosowane:
Jest on testowany w
bash
,dash
,ash
,ksh
,zsh
, ifish
. Niektóre znaki nie wymagają cytowania w niektórych (wersjach) powłok, ale powyższe działa we wszystkich testowanych powłokach.Jeśli chcesz po prostu zacytować ciąg, możesz go potokować w
parallel --shellquote
:źródło
W przypadku lekkiego rozwiązania ucieczki w Perlu, kieruję się zasadą pojedynczych cudzysłowów. Ciąg Bash w pojedynczych cudzysłowach może mieć dowolny znak, z wyjątkiem samego pojedynczego cudzysłowu.
Mój kod:
Przykładowy przebieg 1:
Przykładowy przebieg 2:
Przykładowy przebieg 3:
Przykładowy przebieg 4:
Przykładowy przebieg 5:
źródło