Mam aplikację, która przyjmuje jako atrybuty wejściowe w podwójnych cudzysłowach osadzonych w pojedynczych cudzysłowach. Weźmy na przykład to właściwe polecenie:
command -p 'cluster="cl1"'
Aby to zautomatyzować, stworzyłem plik bash, używając go $CLUSTER
jako zmiennej. Jak powinno być moje polecenie? Innymi słowy, co powinienem umieścić zamiast cl1?
Pamiętaj, że jeśli zmodyfikuję powyższe polecenie, nie zostanie zaakceptowane. Na przykład: command -p "cluster=cl1"
nie jest akceptowane
CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"
cli
bez cudzysłowów wCLUSTER
zmiennej):CLUSTER='cl1'; command -p 'cluster="'"$CLUSTER"'"'
Odpowiedzi:
Wygląda na to, że twoje polecenie może ustawiać zmienne środowiskowe na podstawie argumentów podanych w wierszu poleceń. Być może możesz zrobić:
... i ustaw dla niego swoje środowisko przy wywołaniu.
W przeciwnym razie cudzysłowy powłoki zwykle ograniczają argumenty lub unikają innych specjalnych znaków powłoki przed interpretacją powłoki. Możesz zawierać (i dlatego uciec) różne rodzaje cudzysłowów powłoki w obrębie innych rodzajów w oparciu o różne reguły:
"''''"
- ciąg o miękkich cytatach może zawierać dowolną liczbę twardych cytatów."\""
-\
ukośnik odwrotny może uciec od"
miękkiego cytatu w ciągu"
miękko cytowanego.\\
odwrotny ukośnik również ucieka,\$
token rozwinięcia i\n
ewline jak wspomniano poniżej, ale poza tym jest traktowany dosłownie."${expand} and then some"
- łańcuch z miękkimi cudzysłowami może zawierać interpretowane$
rozwinięcie powłoki .'"\'
-'
ciąg znaków cytowanych na stałe może zawierać dowolny znak inny niż'
ciągły cytat.\
- niecytowany odwrotny ukośnik ucieknie od dowolnego następującego znaku dla dosłownej interpretacji - nawet innego odwrotnego ukośnika - z wyjątkiem\n
ewline.\\n
przypadku ewline\
odwrotny ukośnik i\n
ewline są całkowicie usuwane z wynikowej interpretowanej komendy.${parameter+expand "$parameter"}
- cytaty wynikające z rozszerzenia powłoki prawie nigdy nie służą jako znaczniki separatora, z wyjątkiem kilku specjalnych przypadków. Nie zaryzykuję opisania ich tutaj.Uważam za dziwne, że jakakolwiek aplikacja interpretuje cudzysłowy w argumentach wiersza poleceń. Taka praktyka nie ma większego sensu w tym, że - przynajmniej w przypadku powłok - głównym celem cytatu jest na ogół rozgraniczenie argumentu. Przy wywołaniu jednak argumenty zawsze są już ograniczone ze
\0NUL
znaków, a więc cytat nie może służyć wiele celów.Nawet powłoka zwykle z trudem interpretuje cudzysłowy w jednym z argumentów wywołania, gdy jest wywoływana
-c
przełącznikiem - co oznacza, że jej pierwszy operand jest tak naprawdę skryptem powłoki, który powinien uruchomić przy wywołaniu. Jest to przypadek dwukrotnej oceny danych wejściowych.To powiedziawszy, możesz zrobić wiele rzeczy, aby przekazać dosłowne cudzysłowy za pomocą argumentów w wierszu poleceń. Na przykład:
Jak zauważyłem w komentarzu wcześniej, możesz zawierać
"
cytaty w rozwinięciu, które jest"
cytowane.Możesz uciec
"
z\
ukośnikiem odwrotnym w"
cytowanym ciągu.Możesz zamieniać i łączyć style cytowania, aby osiągnąć pożądany efekt końcowy, jak w notatkach @jimmij powyżej .
Możesz wyłączyć zarówno generowanie, jak i
$IFS
dzielenie nazw plików - unikając w ten sposób konieczności cytowania$expansion
- a więc tylko cytowania. To prawdopodobnie przesada.Na koniec można użyć innego rodzaju cytowania powłoki. Jak zauważyłem wcześniej,
sh -c "$scriptlet"
forma wywoływania powłoki jest często używana do zapewnienia skryptu powłoki w wierszu poleceń. Kiedy$scriptlet
się komplikuje - na przykład gdy cytaty muszą zawierać inne cytaty - często korzystne może być użycie dokumentu tutaj, ash -s
zamiast tego - gdy powłoka jest specjalnie instruowana, aby przypisać wszystkie następujące argumenty do parametrów pozycyjnych, tak jak w-c
przypadku i jeszcze do wzięcia skryptustdin
.Jeśli twoje polecenie musi interpretować cytaty w ten sposób, uważam, że lepiej byłoby, gdyby mógł to zrobić w pliku wejściowym. Na przykład:
Jeśli nie cytujesz separatora
<<here-document
a, cała jej zawartość jest traktowana prawie dokładnie tak, jak w"
cudzysłowie - z tym wyjątkiem, że"
same cudzysłowy nie są traktowane specjalnie. Jeśli więc uruchomimy powyższe zcat
:... drukuje ...
źródło
Jak napisał Mikeserv :
„Double cytat” każdy dosłowne, że zawiera spacje / metaznaki i każdy rozbudowa:
"$var"
,"$(command "$var")"
,"${array[@]}"
,"a & b"
. Użyj'single quotes'
kodu lub dosłowny$'s: 'Costs $5 US'
,ssh host 'echo "$HOSTNAME"'
. Zobaczhttp://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words
źródło
"
znaków - tylko pierwsza i ostatnia powinna wystarczyć. Prawdziwy problem polega na tym, że Twoja aplikacja interpretuje cytaty w arg. Interpretacja cytatu w argumencie prawie nigdy nie jest dobrym pomysłem, ponieważ cytat powinien być jedynie środkiem do rozgraniczenia argumentu - i przy wywołaniu, separacja jest obsługiwana przez\0NUL
s w każdym przypadku. Prawdopodobnie istnieje lepszy sposób na przekazanie informacji, które chcesz do aplikacji? Podoba ci sięcommand --'script=/path/to/some/file'
?