echo
Polecenie nie jest w tym pełny tekst, który daję. Na przykład, jeśli zrobię:
$ echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` '
Wyprowadza:
echo PARAM=` grep $ARG /var/tmp/setfile | awk {print } `
Pojedyncze cudzysłowy ( '
), które miałem w poleceniu echa, nie są uwzględnione. Jeśli przejdę na podwójne cudzysłowy:
$ echo " echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` "
echo
w ogóle nic nie wyświetla! Dlaczego pomija pojedyncze cudzysłowy w pierwszym przykładzie i nic nie daje w drugim? Jak uzyskać to, aby wyświetlało dokładnie to, co wpisałem?
Odpowiedzi:
Twoja powłoka interpretuje cytaty,
'
i"
zanim jeszcze do nich dojdąecho
. Generalnie po prostu umieszczam podwójne cytaty wokół mojego argumentu, aby powtórzyć, nawet jeśli są niepotrzebne; na przykład:Tak więc w pierwszym przykładzie, jeśli chcesz dołączyć dosłowne znaki cudzysłowu, musisz je usunąć:
Lub muszą być już użyte w cytowanym argumencie (ale nie może to być ten sam cytat, inaczej trzeba będzie uciec):
W drugim przykładzie uruchomiono podstawienie polecenia w środku ciągu:
Rzeczy, które zaczynają się,
$
są również obsługiwane przez powłokę - traktuje je jak zmienne i zastępuje ich wartościami. Ponieważ najprawdopodobniej żadna z tych zmiennych nie jest ustawiona w twojej powłoce, tak naprawdę po prostu działaPonieważ
grep
widzi tylko jeden argument, zakłada, że ten argument jest wzorcem, którego szukasz, i że miejscem, z którego powinien odczytać dane, jest standardowe, więc blokuje oczekiwanie na dane wejściowe. Dlatego wydaje się, że twoje drugie polecenie po prostu się zawiesiło.Nie stanie się tak, jeśli zacytujesz argument pojedynczo (dlatego właśnie twój pierwszy przykład prawie działał), więc jest to jeden ze sposobów uzyskania pożądanego wyniku:
Możesz także zacytować go dwukrotnie, ale wtedy będziesz musiał uciec od
$
s, aby powłoka nie rozpoznała ich jako zmiennych, a także backsticks, aby powłoka nie uruchomiła od razu podstawiania poleceń:źródło
Nie będę szczegółowo omawiał, dlaczego wasze próby zachowują się tak, jak się zachowują, ponieważ odpowiedź Michała Mrożka obejmuje to dobrze. W skrócie, wszystko pomiędzy pojedynczymi cudzysłowami (
'…'
) jest interpretowane dosłownie (w szczególności pierwszy'
oznacza koniec ciągu dosłownego),`
a jednocześnie$
zachowują swoje specjalne znaczenie między"…"
.Nie ma cytowania w pojedynczych cudzysłowach, więc nie można wstawić pojedynczego cudzysłowu w ciągu pojedynczego cudzysłowu. Istnieje jednak idiom, który wygląda tak:
Wypisuje się
foo'bar
, ponieważ argumentecho
składa się z trzyznakowego ciągu o pojedynczym cudzysłowiefoo
, połączonego z pojedynczym znakiem'
(uzyskanym przez ochronę znaku'
przed jego specjalnym znaczeniem przez poprzedni\
), połączonego z ciągiem z pojedynczym cudzysłowembar
. Chociaż nie do końca dzieje się to za kulisami, możesz pomyśleć o'\''
sposobie umieszczenia pojedynczego cudzysłowu w ciągu pojedynczego cudzysłowu.Jeśli chcesz drukować złożone ciągi wielowierszowe, lepszym narzędziem jest dokument tutaj . Dokument tutaj składa się z dwóch znaków,
<<
po których następuje znacznik, taki jak<<EOF
, następnie niektóre wiersze tekstu, a następnie sam znacznik końcowy na linii. Jeśli znacznik jest cytowany w jakikolwiek sposób ('EOF'
lub"EOF"
lub\EOF
„E” „OF” lub…), wówczas tekst jest interpretowany dosłownie (jak w pojedynczych cudzysłowach, z tym wyjątkiem, że nawet'
jest zwykłym znakiem). Jeśli znacznik nie jest w ogóle cytowany, tekst jest interpretowany jak ciąg podwójny,$\`
zachowując swój specjalny status (ale"
znaki nowej linii są interpretowane dosłownie).źródło
Ok, to zadziała:
Testowanie tutaj: -
źródło
Sugestia Gillesa, by użyć tutaj dokumentu jest naprawdę miła, a nawet działa w językach skryptowych takich jak Perl. Jako konkretny przykład oparty na jego odpowiedzi na problem PO:
To prawda, że ten przykład jest nieco wymyślony, ale uważam, że jest to przydatna technika, powiedzmy, wysyłania instrukcji SQL na adres
psql
(zamiastcat
).(Zauważ, że dowolny niealfanumeryczny znak spacji może być użyty zamiast
#
ogólnej konstrukcji cytowania powyżej, ale skrót wydaje się dobrze wyróżniać w tym przykładzie i nie jest traktowany jako komentarz).źródło
Weźmy twoje polecenie
i najpierw podziel go na słowa, używając cudzysłowu jako cudzysłowu:
Następnie dokonujemy rozszerzenia parametrów: rozwiń,
$…
ale nie wewnątrz'…'
. Ponieważ$2
jest pusty (chyba że ustawisz go np.set -- …
), Zostanie zastąpiony pustym ciągiem.Następnie usuń wycenę.
Argumenty te są następnie przekazywane do echa, które wypisze je jeden po drugim, oddzielone pojedynczą spacją.
Mam nadzieję, że ta instrukcja krok po kroku uczyni obserwowane zachowanie wyraźniejszym. Aby uniknąć tego problemu, unikaj pojedynczych cudzysłowów:
Spowoduje to zakończenie ciągu pojedynczego cudzysłowu, następnie doda (cudzą literę) pojedynczy cytat do słowa, a następnie rozpocznie nowy ciąg pojedynczego cudzysłowu, bez rozbijania słowa na części.
źródło