Chcę uruchomić polecenie ze skryptu bash, który zawiera pojedyncze cudzysłowy i niektóre inne polecenia wewnątrz pojedynczych cudzysłowów i zmienną.
na przykład repo forall -c '....$variable'
W tym formacie $
jest zastępowany, a zmienna nie jest rozwijana.
Próbowałem następujących odmian, ale zostały one odrzucone:
repo forall -c '...."$variable" '
repo forall -c " '....$variable' "
" repo forall -c '....$variable' "
repo forall -c "'" ....$variable "'"
Jeśli podstawię wartość zamiast zmiennej, polecenie zostanie wykonane dobrze.
Powiedz mi, gdzie się mylę.
repo forall -c ' ...before... '"$variable"' ...after...'
bash
zjada pojedyncze cytaty. Albo cię nie mabash
, albo pojedyncze cudzysłowy nie są częściąrepo
polecenia.Odpowiedzi:
Wewnątrz pojedynczych cytatów wszystko jest zachowane dosłownie, bez wyjątku.
Oznacza to, że musisz zamknąć cytaty, wstawić coś, a następnie ponownie wprowadzić.
Łączenie słów odbywa się po prostu przez zestawienie. Jak możesz zweryfikować, każdy z powyższych wierszy jest pojedynczym słowem w powłoce. Cytaty (pojedyncze lub podwójne, w zależności od sytuacji) nie izolują słów. Służą one wyłącznie do wyłączania interpretacji różnych znaków specjalnych, takich jak białe znaki
$
,;
... Aby uzyskać dobry samouczek na temat cytowania, zobacz odpowiedź Marka Reeda. Również istotne: Które postacie muszą być poprzedzone ucieczką?Nie łącz łańcuchów interpretowanych przez powłokę
Należy bezwzględnie unikać budowania poleceń powłoki poprzez łączenie zmiennych. Jest to zły pomysł podobny do łączenia fragmentów SQL (wstrzyknięcie SQL!).
Zwykle możliwe jest umieszczenie symboli zastępczych w poleceniu i dostarczenie polecenia wraz ze zmiennymi, aby odbiorca mógł je odebrać z listy argumentów wywołania.
Na przykład następujące jest bardzo niebezpieczne. NIE Rób tego
Jeśli zawartość
$myvar
jest niezaufana, oto exploit:Zamiast powyższego wywołania użyj argumentów pozycyjnych. Następujące wywołanie jest lepsze - nie można go wykorzystać:
Zwróć uwagę na użycie pojedynczych znaczników w przypisaniu do
script
, co oznacza, że przyjmuje się dosłownie, bez zmiennej interpretacji lub jakiejkolwiek innej formy interpretacji.źródło
"some"thing' like'this
to jedno słowo do powłoki. Znaki cudzysłowu nie kończą niczego w zakresie analizowania i nie ma sposobu, aby polecenie wywoływane przez powłokę informowało o tym, co zostało zacytowane.repo
Polecenie nie może obchodzi jakie cytaty robi. Jeśli potrzebujesz rozszerzenia parametrów, użyj podwójnych cudzysłowów. Jeśli to oznacza, że musisz skończyć z odwrotnym ukośnikiem wiele rzeczy, użyj pojedynczych cudzysłowów dla większości z nich, a następnie wyrwij się z nich i przejdź do podwójnych w części, w której potrzebujesz rozszerzenia.Wyjaśnienie następuje, jeśli jesteś zainteresowany.
Po uruchomieniu polecenia z powłoki to polecenie otrzymuje jako argumenty tablicę ciągów zakończonych znakiem null. Ciągi te mogą zawierać absolutnie dowolny znak inny niż zero.
Ale gdy powłoka buduje tablicę ciągów z wiersza poleceń, interpretuje niektóre znaki specjalnie; ma to na celu ułatwienie (a nawet możliwość) wykonywania poleceń. Na przykład spacje zwykle wskazują granicę między łańcuchami w tablicy; z tego powodu poszczególne argumenty są czasami nazywane „słowami”. Niemniej jednak w sporze mogą znajdować się spacje; potrzebujesz tylko sposobu, aby powiedzieć powłoce, że tego chcesz.
Możesz użyć odwrotnego ukośnika przed dowolną postacią (w tym spacją lub innym odwrotnym ukośnikiem), aby powiedzieć powłoce, aby traktowała tę postać dosłownie. Ale chociaż możesz zrobić coś takiego:
echo \"Thank\ you.\ \ That\'ll\ be\ \$4.96,\ please,\"\ said\ the\ cashier
... może być męczące. Powłoka oferuje więc alternatywę: znaki cudzysłowu. Występują w dwóch głównych odmianach.
Podwójne cudzysłowy nazywane są „grupowaniem cudzysłowów”. Zapobiegają rozszerzaniu symboli wieloznacznych i aliasów, ale głównie służą do umieszczania spacji w słowie. Inne rzeczy, takie jak rozszerzanie parametrów i poleceń (rzeczy sygnalizowane przez a
$
) nadal występują. I oczywiście, jeśli chcesz literalnego podwójnego cudzysłowu w cudzysłowach, musisz odwrócić ukośnik:echo "\"Thank you. That'll be \$4.96, please,\" said the cashier"
Znaki pojedynczego cudzysłowu są bardziej drakońskie. Wszystko między nimi jest brane całkowicie dosłownie, łącznie z odwrotnymi ukośnikami. Nie ma absolutnie żadnego sposobu na uzyskanie dosłownego pojedynczego cytatu w pojedynczych cytatach.
Na szczęście znaki cudzysłowu w powłoce nie są ogranicznikami słów ; same w sobie nie kończą słowa. Możesz wchodzić i wychodzić z cytatów, w tym między różnymi typami cytatów, w ramach tego samego słowa, aby uzyskać pożądany wynik:
echo '"Thank you. That'\''ll be $4.96, please," said the cashier'
To jest łatwiejsze - dużo mniej odwrotnych ukośników, chociaż przyzwyczajenie się do sekwencji z zamkniętym cytatem, odwróconego literału-pojedynczego cytatu, otwartego pojedynczego cytatu.
Nowoczesne powłoki dodały inny styl cytowania nieokreślony przez standard POSIX, w którym wiodący pojedynczy cudzysłów jest poprzedzony znakiem dolara. Tak cytowane łańcuchy są zgodne z konwencjami podobnymi do literałów łańcuchowych w języku programowania ANSI C i dlatego są czasami nazywane „ciągami ANSI” i
$'
…'
parą „cudzysłowów ANSI”. W przypadku takich ciągów powyższa rada dotycząca dosyłania ukośników dosłownie nie ma już zastosowania. Zamiast tego stają się ponownie wyjątkowe - nie tylko można dołączyć dosłowny pojedynczy cudzysłów lub ukośnik odwrotny, przygotowując do niego odwrotny ukośnik, ale powłoka rozszerza także znaki ucieczki znaku ANSI C (jak\n
dla nowej linii,\t
dla tabu i\xHH
dla znaku z kod szesnastkowyHH
). W przeciwnym razie zachowują się jak ciągi cudzysłowu: nie następuje podstawienie parametru ani polecenia:Należy zauważyć, że pojedynczy ciąg otrzymany jako argument
echo
polecenia jest dokładnie taki sam we wszystkich tych przykładach. Po zakończeniu analizy powłoki w wierszu poleceń nie można uruchomić polecenia, aby powiedzieć, co zostało zacytowane. Nawet gdyby chciał.źródło
$'string'
format jest zgodny z POSIX? Czy jest też na to nazwa?$'string'
jest rozszerzeniem innym niż POSIX, które widziałem jako „ciągi ANSI”; Włączyłem te fakty do odpowiedzi. Takie ciągi działają w większości nowoczesnych powłok kompatybilnych z Bourne: bash, dash, ksh (zarówno AT&T, jak i PD), a wszystkie zsh obsługują je.Poniżej działało dla mnie -
źródło
QUOTE
oddzielnej zmiennej jest całkowicie zbędne; pojedyncze cudzysłowy wewnątrz podwójnych cudzysłowów to tylko zwykły znak. (Również nie używaj wielkich liter do zmiennych prywatnych.)EDYCJA: (Zgodnie z pytaniami :)
Od tego czasu przyglądam się temu. Miałem szczęście, że miałem repozytorium. Nadal nie jest dla mnie jasne, czy trzeba przymusowo umieszczać polecenia między pojedynczymi cudzysłowami. Zajrzałem do składni repo i nie sądzę, żebyś musiał. Możesz użyć podwójnych cudzysłowów wokół swojego polecenia, a następnie użyć dowolnych pojedynczych i podwójnych cudzysłowów, które potrzebujesz w środku, pod warunkiem, że unikniesz podwójnych.
źródło
po prostu użyj printf
zamiast
użyj printf, aby zastąpić token zmiennej zmienną rozwiniętą.
Na przykład:
źródło
printf
tak naprawdę nic tu nie kupuje, a brak cytowania zastępowania poleceń powoduje nowe problemy z cytowaniem.Zmienne mogą zawierać pojedyncze cudzysłowy.
źródło
"$myvar"
podwójne cudzysłowy.Czy to ci odpowiada?
źródło