Powiedzmy, że masz Bash alias
jak:
alias rxvt='urxvt'
co działa dobrze.
Jednak:
alias rxvt='urxvt -fg '#111111' -bg '#111111''
nie będzie działać i nie będzie:
alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''
Więc jak skończysz dopasowywanie otwierających i zamykających cytatów w ciągu, gdy unikniesz cudzysłowów?
alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
wydaje się niezręcznie, chociaż reprezentowałby ten sam ciąg, gdybyś mógł je w taki sposób połączyć.
"\""
dlatego należy je stosować zamiast odpowiedzi @ liori, gdy tylko jest to możliwe.Odpowiedzi:
Jeśli naprawdę chcesz używać pojedynczych cudzysłowów w najbardziej zewnętrznej warstwie, pamiętaj, że możesz przykleić oba rodzaje cudzysłowów. Przykład:
Wyjaśnienie, jak
'"'"'
należy interpretować to jako'
:'
Zakończ pierwszą ofertę, która używa pojedynczych ofert."
Rozpocznij drugą ofertę, używając podwójnych cudzysłowów.'
Cytowana postać."
Zakończ drugi cytat, używając podwójnych cudzysłowów.'
Rozpocznij trzecią ofertę, używając pojedynczych ofert.Jeśli nie umieścisz żadnych białych znaków między (1) i (2) lub między (4) i (5), powłoka zinterpretuje ten ciąg jako jedno długie słowo.
źródło
alias splitpath='echo $PATH | awk -F : '"'"'{print "PATH is set to"} {for (i=1;i<=NF;i++) {print "["i"]",$i}}'"'"
Działa, gdy w ciągu aliasu znajdują się zarówno pojedyncze cudzysłowy, jak i podwójne cudzysłowy!alias serve_this_dir='ruby -rrack -e "include Rack;Handler::Thin.run Builder.new{run Directory.new'"'"''"'"'}"'
'\''
jest znacznie bardziej czytelny w większości kontekstów niż'"'"'
. W rzeczywistości pierwsza z nich jest prawie zawsze wyraźnie wyraźna w ciągu pojedynczego cudzysłowu, a zatem jest tylko kwestią przyporządkowania go semantycznie do znaczenia „jest to cytowany znak ucieczki”, tak jak\"
w przypadku ciągów podwójnych cudzysłowów. Podczas gdy ten ostatni łączy się w jedną linię cytatów i w wielu przypadkach wymaga dokładnej kontroli, aby właściwie rozróżnić.Zawsze po prostu zastępuję każdy osadzony pojedynczy cytat sekwencją:
'\''
(to znaczy: quote backslash quote quote), która zamyka ciąg, dołącza do niego pojedynczy cytat i otwiera go ponownie.Często używam funkcji cytowania w moich skryptach Perla, aby to dla mnie zrobić. Kroki byłyby następujące:
To właściwie zajmuje się wszystkimi sprawami.
Życie staje się przyjemniejsze po wprowadzeniu
eval
do skryptów powłoki. Zasadniczo musisz ponownie wszystko wycenić!Na przykład utwórz skrypt Perla o nazwie quote zawierający powyższe instrukcje:
następnie użyj go, aby wygenerować poprawnie cytowany ciąg:
wynik:
które można następnie skopiować / wkleić do polecenia aliasu:
(Jeśli musisz wstawić polecenie do eval, uruchom cytat ponownie:
wynik:
które można skopiować / wkleić w eval:
źródło
set -x
iecho "here's a string"
zobaczysz, że bash się wykonujeecho 'here'\''s a string'
. (set +x
aby przywrócić normalne zachowanie)Ponieważ składnia Bash 2.04
$'string'
(zamiast po prostu'string'
; ostrzeżenie: nie mylić z$('string')
) jest kolejnym mechanizmem cytowania, który pozwala na sekwencje specjalne ANSI podobne do C i umożliwia rozszerzenie do wersji pojedynczego cytatu.Prosty przykład:
W Twoim przypadku:
Typowe sekwencje specjalne działają zgodnie z oczekiwaniami:
Poniżej znajduje się kopia + wklejona powiązana dokumentacja z
man bash
(wersja 4.4):Słowa w postaci $ „string” są traktowane specjalnie. Słowo jest interpretowane jako ciąg znaków, a znaki specjalne z odwrotnym ukośnikiem są zastępowane zgodnie ze standardem ANSI C. Sekwencje specjalne odwrotnego ukośnika, jeśli występują, są dekodowane w następujący sposób:
Rozwinięty wynik jest cytowany pojedynczo, tak jakby znak dolara nie był obecny.
Zobacz cytaty i ucieczkę: ciągi ANSI C na wiki bash-hackers.org, aby uzyskać więcej informacji. Zwróć też uwagę, że plik „Bash Changes” ( tutaj omówienie ) wiele wspomina o zmianach i poprawkach błędów związanych z
$'string'
mechanizmem cytowania.Według unix.stackexchange.com Jak używać znaku specjalnego jako normalnego? powinien działać (z pewnymi odmianami) w bash, zsh, mksh, ksh93 oraz FreeBSD i busybox sh.
źródło
echo $'foo\'b!ar'
=>!ar': event not found
> echo $BASH_VERSION
4.2.47(1)-release
> echo $'foo\'b!ar'
foo'b!ar
$'
więc prawdopodobnie najłatwiejszym sposobem jest wypróbowanie go na starszych systemach.e. Bash no longer inhibits C-style escape processing ($'...') while performing pattern substitution word expansions.
z tiswww.case.edu/php/chet/bash/CHANGES . Nadal działa w wersji 4.3.42, ale nie w wersji 4.3.48.Nie widzę wpisu na jego blogu (link pls?), Ale zgodnie z podręcznikiem GNU :
więc bash nie zrozumie:
alias x='y \'z '
możesz to jednak zrobić, jeśli otaczasz się podwójnymi cudzysłowami:
źródło
Mogę potwierdzić, że użycie
'\''
pojedynczego cudzysłowu w ciągu pojedynczego cudzysłowu działa w języku Bash i można to wyjaśnić w taki sam sposób, jak argument „sklejanie” z wcześniejszego wątku. Załóżmy, że mamy ciąg cudzysłowu:'A '\''B'\'' C'
(wszystkie cytaty tutaj są pojedynczymi cudzysłowami). Jeśli jest ona przekazywana do echo, drukuje, co następuje:A 'B' C
. W każdym'\''
pierwszym cytacie zamyka bieżący ciąg pojedynczego cudzysłowu, poniższy\'
przykleja pojedynczy cytat do poprzedniego ciągu (\'
jest to sposób na określenie pojedynczego cytatu bez rozpoczynania cytowanego ciągu), a ostatni cytat otwiera kolejny ciąg pojedynczego cudzysłowu.źródło
alias something='A '\''B'\'' C'
powoduje,something
że jest to pojedynczy ciąg, więc nawet jeśli prawa strona zadania nie jest technicznie pojedynczym ciągiem, nie sądzę, żeby miało to duże znaczenie.'A ' + ' + 'B' + ' + ' C'
. Innymi słowy, rozwiązanie polegające na wstawianiu znaków pojedynczego cudzysłowu w ciągu pojedynczego cudzysłowu powinno pozwolić mi stworzyć taki ciąg i wydrukować go. Jednak to rozwiązanie nie będzie działać w tym przypadku.STR='\''; echo $STR
. Zgodnie z projektem BASH tak naprawdę na to nie pozwala.'\''
działa na bash. Czy możesz wskazać, które sekcje gnu.org/software/bash/manual/bashref.html określają takie zachowanie?Obie wersje działają albo z konkatenacją przy użyciu znaku ucieczki pojedynczego cudzysłowu (\ '), albo z konkatenacją poprzez umieszczenie znaku pojedynczego cudzysłowu w podwójnych cudzysłowach („” ”).
Autor pytania nie zauważył, że na końcu ostatniej próby ucieczki był dodatkowy pojedynczy cytat ('):
Jak widać na poprzednim ładnym dziele ASCII / Unicode, po ostatnim cytowanym pojedynczym cudzysłowie (\ ') następuje niepotrzebny pojedynczy cudzysłów ('). Bardzo pomocne może być użycie wyróżniacza składni, takiego jak ten obecny w Notepad ++.
To samo dotyczy innego przykładu, takiego jak następujący:
Te dwa piękne przykłady aliasów pokazują w bardzo skomplikowany i zaciemniony sposób, w jaki sposób plik może zostać wyrównany. Oznacza to, że z pliku zawierającego wiele linii otrzymujesz tylko jedną linię z przecinkami i spacjami między zawartością poprzednich linii. Aby zrozumieć poprzedni komentarz, poniżej podano przykład:
źródło
Prosty przykład ucieczki cytatów w powłoce:
Odbywa się to poprzez ukończenie już otwartego (
'
), umieszczenie klawisza Esc (\'
), a następnie otwarcie kolejnego ('
). Ta składnia działa dla wszystkich poleceń. To bardzo podobne podejście do pierwszej odpowiedzi.źródło
Nie zajmuję się konkretnie kwestią cytowania, ponieważ czasami rozsądne jest rozważenie alternatywnego podejścia.
który możesz następnie wywołać jako:
Chodzi o to, że możesz teraz alias to bez obawy o cytaty:
lub, jeśli
#
z jakiegoś powodu musisz uwzględnić we wszystkich połączeniach:który możesz następnie wywołać jako:
wtedy alias to:
(ups, myślę, że w pewnym sensie zająłem się cytowaniem :)
źródło
Ponieważ nie można umieszczać pojedynczych cudzysłowów w ciągach pojedynczych cudzysłowów, najprostszą i najbardziej czytelną opcją jest użycie łańcucha HEREDOC
W powyższym kodzie HEREDOC jest wysyłany do
cat
polecenia, a jego wynik jest przypisywany do zmiennej za pomocą notacji podstawienia polecenia$(..)
Konieczne jest umieszczenie pojedynczego cytatu w HEREDOC, ponieważ jest on w ciągu
$()
źródło
dash
domyślna powłoka w skryptach startowych Ubuntu i gdzie indziej.Po prostu używam kodów powłoki ... np.
\x27
Lub\\x22
w stosownych przypadkach. Bezproblemowo, naprawdę.źródło
x27
(na Centos 6.6)Większość z tych odpowiedzi dotyczy konkretnego przypadku, o który pytasz. Istnieje ogólne podejście, że przyjaciel i ja stworzyliśmy, która pozwala na arbitralne cytowanie w przypadku trzeba cytat bash polecenia za pośrednictwem wielu warstw powłoki, np ekspansji, poprzez ssh
su -c
,bash -c
itp Jest jeden rdzeń prymitywny trzeba tutaj w natywnej bash:Robi dokładnie to, co mówi: powtarza każdy argument osobno (oczywiście po rozszerzeniu basha):
Robi to oczywiste dla jednej warstwy rozszerzenia:
(Zauważ, że podwójne cudzysłowy
$(quote_args ...)
są konieczne, aby wynik był pojedynczym argumentembash -c
.) I można go bardziej ogólnie użyć do cytowania poprawnie poprzez wiele warstw rozwinięcia:Powyższy przykład:
quote_args
indywidualnie, a następnie łączy wynikowy wynik w pojedynczy argument z wewnętrznymi podwójnymi cudzysłowami.bash
,-c
i już po cytowane wynikiem z etapu 1, a następnie łączy się wynik w jeden argument z zewnętrznych cudzysłowach.bash -c
.Taki jest pomysł w pigułce. Możesz robić z tym dość skomplikowane rzeczy, ale musisz uważać na kolejność oceny i na cytowane podciągi. Na przykład następujące czynności są niewłaściwe (w przypadku niektórych definicji „zła”):
W pierwszym przykładzie bash natychmiast rozwija się
quote_args cd /; pwd 1>&2
w dwie osobne komendy,quote_args cd /
apwd 1>&2
więc CWD jest nadal w/tmp
trakcie wykonywaniapwd
komendy. Drugi przykład ilustruje podobny problem z globowaniem. Rzeczywiście ten sam podstawowy problem występuje w przypadku wszystkich rozszerzeń bash. Problem polega na tym, że podstawienie polecenia nie jest wywołaniem funkcji: dosłownie ocenia jeden skrypt bash i wykorzystuje jego dane wyjściowe jako część innego skryptu bash.Jeśli spróbujesz po prostu uciec operatorom powłoki, nie powiedzie się, ponieważ przekazany ciąg znaków
bash -c
jest po prostu sekwencją pojedynczo cytowanych ciągów, które nie są następnie interpretowane jako operatory, co jest łatwe do zauważenia, jeśli powtórzy się ciąg zostały przekazane do bash:Problem polega na tym, że przesadzasz. Potrzebne jest, aby operatory nie były cytowane jako dane wejściowe do załączania
bash -c
, co oznacza, że muszą znajdować się poza$(quote_args ...)
podstawianiem poleceń.W związku z tym, co musisz zrobić w najbardziej ogólnym sensie, to zacytowanie powłoki każdego słowa polecenia, które nie jest przeznaczone do rozszerzenia w momencie podstawiania polecenia osobno, i nie stosuj żadnego dodatkowego cudzysłowu dla operatorów powłoki:
Gdy to zrobisz, cały ciąg jest uczciwą grą do dalszego cytowania na dowolnych poziomach oceny:
itp.
Te przykłady mogą wydawać wymęczony zważywszy, że słowa takie jak
success
,sbin
ipwd
nie trzeba być powłoka cytowany, ale kluczowy punkt, aby pamiętać przy pisaniu skryptu biorąc dowolny wejście jest, że chcesz zacytować wszystko nie jesteś absolutnie pewny robi” t trzeba przytoczyć, bo nigdy nie wiadomo, kiedy użytkownik będzie rzucać wRobert'; rm -rf /
.Aby lepiej zrozumieć, co dzieje się pod przykryciem, możesz bawić się przy pomocy dwóch małych funkcji pomocniczych:
, który wyliczy każdy argument do polecenia przed jego wykonaniem:
źródło
vagrant ssh -c {single-arg} guest
. Te{single-arg}
muszą być traktowane jako pojedynczy arg ponieważ włóczęga zajmuje następnego argumentu po nim, jak nazwa gościa. Nie można zmienić zamówienia. Ale musiałem przekazać polecenie i jego argumenty{single-arg}
. Więc użyłem swojejquote_args()
zacytować polecenia i jego argumenty, i umieścić w cudzysłowie wynik, i to działało jak czar:vagrant ssh -c "'command' 'arg 1 with blanks' 'arg 2'" guest
. Dzięki!!!IMHO prawdziwą odpowiedzią jest to, że nie można uciec przed pojedynczymi cudzysłowami w ciągach pojedynczych cudzysłowów.
To niemożliwe.
Jeśli założymy, że używamy bash.
Z podręcznika bash ...
Musisz użyć jednego z pozostałych mechanizmów zmiany ciągu znaków ”lub \
Nie ma w tym nic magicznego
alias
wymagałoby użycia pojedynczych cudzysłowów.Obie poniższe prace działają w bashu.
Ten ostatni używa \ do zmiany znaku spacji.
W # 111111 nie ma też magii, która wymaga pojedynczych cudzysłowów.
Poniższe opcje osiągają ten sam wynik, co pozostałe dwie opcje, ponieważ alias rxvt działa zgodnie z oczekiwaniami.
Możesz także uciec od kłopotliwego # bezpośrednio
źródło
W podanym przykładzie po prostu użyłem podwójnych cudzysłowów zamiast pojedynczych cudzysłowów jako zewnętrznego mechanizmu zmiany znaczenia:
To podejście jest odpowiednie w wielu przypadkach, w których po prostu chcesz przekazać stały ciąg do polecenia: po prostu sprawdź, jak powłoka zinterpretuje ciąg cudzysłowu poprzez
echo
, jeśli to konieczne, znaki specjalne z odwrotnym ukośnikiem.W tym przykładzie widać, że podwójne cudzysłowy są wystarczające do ochrony ciągu:
źródło
Oczywiście łatwiej byłoby po prostu otoczyć podwójnymi cudzysłowami, ale w czym to wyzwanie? Oto odpowiedź przy użyciu tylko pojedynczych cudzysłowów. Używam zmiennej zamiast,
alias
więc łatwiej jest wydrukować dowód, ale to samo co przy użyciualias
.Wyjaśnienie
Kluczem jest to, że możesz zamknąć pojedynczy cytat i otworzyć go tyle razy, ile chcesz. Na przykład
foo='a''b'
jest taki sam jakfoo='ab'
. Abyś mógł zamknąć pojedynczy cytat, dodać dosłowny pojedynczy cytat\'
, a następnie ponownie otworzyć następny pojedynczy cytat.Schemat podziału
Ten schemat wyjaśnia, używając nawiasów kwadratowych, aby pokazać, gdzie pojedyncze cudzysłowy są otwierane i zamykane. Cytaty nie są „zagnieżdżone”, jak mogą być nawiasy. Możesz także zwrócić uwagę na prawidłowe podświetlanie kolorów. Cytowane struny są bordowe, a
\'
czarne.(Jest to zasadniczo ta sama odpowiedź, co odpowiedź Adriana, ale wydaje mi się, że to wyjaśnia lepiej. Również jego odpowiedź zawiera 2 zbędne pojedyncze cytaty na końcu.)
źródło
'\''
metody, którą polecam, zamiast'"'"'
metody, która często jest trudniejsza do odczytania przez ludzi.Oto opracowanie na temat The One True Odpowiedź, o której mowa powyżej:
Czasami będę pobierać za pomocą rsync przez ssh i muszę uciec od nazwy pliku z 'DWUKROTNIE! (OMG!) Raz dla bash i raz dla ssh. Działa tutaj ta sama zasada naprzemiennego ograniczania cudzysłowów.
Na przykład, powiedzmy, że chcemy zdobyć: Historie LA Louisa Therouxa ...
I oto! Skończysz z tym:
co jest strasznie dużo pracy dla jednego malucha ”- ale proszę bardzo
źródło
Wyjaśnienie wykonania:
podwójne cudzysłowy, dzięki czemu możemy łatwo wyprowadzać zawijanie pojedynczych cudzysłowów i używać
${...}
składniWyszukiwanie i zamiana bash wygląda następująco:
${varname//search/replacement}
jesteśmy wymianie
'
z'\''
'\''
koduje taki singiel'
:'
kończy pojedynczy cytat\'
koduje a'
(odwrotny ukośnik jest potrzebny, ponieważ nie znajdujemy się w cudzysłowach)'
ponownie rozpoczyna pojedynczy cytatbash automatycznie łączy łańcuchy bez odstępów między nimi
jest
\
przed wszystkim\
i'
dlatego, że są to zasady ucieczki${...//.../...}
.PS Zawsze koduje ciągi pojedynczego cudzysłowu, ponieważ są one znacznie prostsze niż ciągi podwójnie cytowane.
źródło
Inny sposób rozwiązania problemu zbyt wielu warstw zagnieżdżonego cytatu:
Próbujesz wcisnąć za dużo w zbyt małą przestrzeń, więc użyj funkcji bash.
Problem polega na tym, że próbujesz mieć zbyt wiele poziomów zagnieżdżania, a podstawowa technologia aliasów nie jest wystarczająco silna, aby ją pomieścić. Użyj funkcji bash w ten sposób, aby pojedyncze, podwójne cudzysłowy zwrotne i przekazane parametry były obsługiwane normalnie, jak można by się spodziewać:
Następnie możesz użyć zmiennych 1 $ i 2 $ oraz pojedynczych, podwójnych cudzysłowów i tyknięć, nie martwiąc się o to, że funkcja aliasu psuje ich integralność.
Ten program drukuje:
źródło
Jeśli masz zainstalowany GNU Parallel, możesz użyć jego wewnętrznego cytowania:
Od wersji 20190222 możesz nawet
--shellquote
wiele razy:Cytuje ciąg znaków we wszystkich obsługiwanych powłokach (nie tylko
bash
).źródło
Ta funkcja:
pozwala na cytowanie
'
wnętrza'
. Użyj tego:Jeśli wiersz do cytowania staje się bardziej złożony, np. Podwójne cudzysłowy zmieszane z pojedynczymi cudzysłowami, uzyskanie ciągów do cytowania w zmiennej może być dość trudne. Kiedy pojawią się takie przypadki, napisz dokładny wiersz, który musisz zacytować w skrypcie (podobnie do tego).
Wyjdzie:
Wszystkie poprawnie cytowane ciągi znaków w pojedynczych cudzysłowach.
źródło
Jeśli generujesz ciąg powłoki w Pythonie 2 lub Pythonie 3, poniższe cytaty mogą pomóc w cytowaniu argumentów:
Spowoduje to:
źródło
Oto moje dwa centy - w przypadku, gdy ktoś chce być
sh
przenośny, a nie tylkobash
specyficzny (rozwiązanie nie jest jednak zbyt wydajne, ponieważ uruchamia program zewnętrzny -sed
):quote.sh
(lub po prostuquote
) gdzieś na swoimPATH
:Przykład:
I to oczywiście przekształca:
Objaśnienie: w zasadzie musimy ująć dane wejściowe w cudzysłów
'
, a następnie zamienić dowolny pojedynczy cytat w tym mikrodźwięku:'"'"'
(zakończ otwierający cytat parowaniem'
, uniknij znalezionego pojedynczego cytatu, zawijając go podwójnymi cudzysłowami -"'"
i wreszcie wydać nowe otwarcie pojedynczego cudzysłowu'
lub w pseudo-notacji:' + "'" + ' == '"'"'
)Jednym ze standardowych sposobów na wykonanie tego byłoby użycie
sed
następującej komendy podstawiania:Jednym małym problemem jest to, że aby użyć tego w powłoce, trzeba uciec od wszystkich tych pojedynczych cudzysłowów w samym wyrażeniu sed - co prowadzi do czegoś takiego jak
(a jednym dobrym sposobem na zbudowanie tego wyniku jest nakarmienie oryginalnego wyrażenia
s/\(['][']*\)/'"\1"'/g
skryptami Kyle'a Rose'a lub George'a V. Reilly'ego).Wreszcie, sensowne jest oczekiwanie, że dane wejściowe będą pochodzić
stdin
- ponieważ przekazywanie ich przez argumenty wiersza poleceń może być już zbyt dużym problemem.(Och, być może chcemy dodać mały komunikat pomocy, aby skrypt nie zawiesił się, gdy ktoś po prostu go uruchomi, ponieważ
./quote.sh --help
zastanawia się, co robi).źródło
Oto inne rozwiązanie. Ta funkcja pobiera pojedynczy argument i odpowiednio go zacytuje, używając znaku pojedynczego cudzysłowu, tak jak wyjaśniono w głosowaniu powyżej:
Możesz więc użyć tego w ten sposób:
źródło