Zrozumienie wykrzyknika (!) W bash

108

użyłem

history | less

aby uzyskać wiersze poprzednich poleceń i z liczb po lewej stronie znalazłem wiersz, który chciałem powtórzyć (np. 22) i zrobiłem

!22

w wierszu polecenia i zadziałało - wykonanie zestawu poleceń w wierszu, który zrobiłem w tym czasie. Nie mogę dowiedzieć się, gdzie jest używany wykrzyknik, co reprezentuje pod względem działań podejmowanych przez bash i gdzie go użyć. Z dokumentacji nie widzę wyjaśnienia, które byłoby „namacalne”.

Vass
źródło
6
Ta odpowiedź może pomóc
Michał Mrożek
9
Nie jest to odpowiedź na twoje pytanie, ale <ctrl> + R pozwoli ci interaktywnie przeszukać swoją historię, a następnie natychmiast wykonać, jeśli znajdziesz to, czego szukałeś.
kasterma

Odpowiedzi:

144

!to funkcja, która pierwotnie pojawiła się w powłoce C , jeszcze w czasach, zanim można było liczyć na terminale posiadające klawisze strzałek. Jest to szczególnie przydatne, jeśli dodasz bieżący numer polecenia do znaku zachęty ( PS1="\!$ "), dzięki czemu możesz szybko spojrzeć na ekran, aby uzyskać numery poprzednich poleceń.

Teraz, gdy możesz używać klawiszy strzałek i takich rzeczy, jak Ctrl-Rprzeszukiwanie historii poleceń, nie widzę dużego zastosowania tej funkcji.

Jednym z jego wariantów, który może być nadal przydatny, jest !!ponowne wykonanie poprzedniego polecenia. Sam w sobie nie znajduję !!Enterszybszego niż tylko Enter, ale może być pomocny w połączeniu z większym poleceniem.

Przykład: Częstym błędem pilota w sudosystemach opartych jest zapomnienie sudoprefiksu polecenia wymagającego dodatkowych uprawnień. Nowicjusz przepisuje całe polecenie. Pilny uczeń edytuje polecenie z historii poleceń powłoki. Oświecony jeden typ sudo !!.

Bash pozwala wyłączyć !przetwarzanie w powłoce za pomocą set +o histexpandlub set +H. Możesz to wyłączyć w Zsh za pomocą set -K.

Warren Young
źródło
4
Uważam, że Ctrl-P Ctrl-J jest dość szybki; przynajmniej szybciej niż w górę Enter.
ephemient
24
Jeśli chcesz tylko uruchomić ostatnie polecenie, w górę / Enter jest w porządku, ale jeśli chcesz je w jakiś sposób dodać (powiedz, że zapomniałeś sudolub coś takiego), możesz to zrobić sudo !!na przykład. Może to być nieco szybsze niż „Up / Ctrl-A (lub Home, jeśli masz szczęście) / sudo / space / enter”. YMMV. :)
1
@AquariusPower: Wystarczy zacytować. Albo echo 'Hi!'albo echo "Hi!"albo echo Hi\!. Wszyscy robią to samo.
Warren Young,
1
setopt NO_BANG_HISTw Zsh może być bardziej niezapomniany niż -K.
gregory
48

Jeśli nie ma tutaj dłuższej odpowiedzi, na pewno jest jedna na Super User, ponieważ niedawno ją przeczytałem. Na stronie podręcznika użytkownika bash można znaleźć ogromną sekcję zatytułowaną HISTORIA EXPANSION w tej sprawie.

Możesz zrobić cały host więcej niż tylko uruchomić ostatnią komendę lub komendę o numerze X. Możesz zrobić rzeczy takie jak !caturuchomienie ostatniej komendy, która się rozpoczęła cat. Lub !?bash?:s/bash/csh/uruchamia ostatnie polecenie zawierające, bashale zastępuje je csh.

Cry Havok
źródło
3
Chociaż nie jest to bezpośrednia odpowiedź na pytanie OP, wymaga to znacznie większej aprobaty. Tak przydatne! Dzięki, Havok.
malvim
Powinienem naprawdę zajrzeć na stronę podręcznika, zanim zacznę googlować.
erikbwork
1
!!:s/bash/csh/faktycznie uruchamia ostatnie polecenie , a następnie zastępuje bash csh, jeśli jest obecny. Nie ostatnie polecenie zawierające bash. To byłoby, !?bash?:s/bash/csh/a może!?bash?:s/%/csh/
cde
Po kilku latach intensywnego korzystania z Basha byłem zszokowany, gdy dowiedziałem się, że nigdy wcześniej nie znałem tego słowa kluczowego, i mimo że spędziłem wiele godzin przeglądając manstrony, ta funkcja jest niesamowicie niejasna. Dziękujemy za wskazanie odpowiedniej sekcji - to jedyne miejsce w rzeczywistych dokumentach, w którym wystarczająco to wyjaśniają.
Steve Benner
39

Można zrobić o wiele więcej dzięki !:

  • wykonaj polecenie wpisane przed 3 poleceniami: !-3
  • wykonać polecenie zaczynające się od !ls

i dużo więcej. Zobacz 15 przykładów ekspansji historii Linuksa, które powinieneś znać

użytkownik379997
źródło
Poparłem to. Żadna z pozostałych odpowiedzi nie zawierała żadnej z tych sprytnych sztuczek.
Gergely Lukacsy
Głosowano, ponieważ www.thegeekstuff.com to po prostu fantastyczny zasób, i był to jeden z niewielu artykułów na temat Linuksa, których wcześniej nie widziałem. Bardzo pomocny.
Steve Benner
4

Mój przyjaciel wysłał mi to e-mailem:

Jest częścią biblioteki historii GNU. W bash służy do ponownego uruchamiania poleceń w twojej historii. Jeśli chcesz być hardcorem, grep dla history_expansion_char w bash-4.1 / lib / readline / histexpand.c, aby uzyskać szczegółowe informacje na temat implementacji.

Vass
źródło
3

Oczywiście możesz zrobić, !!aby ponownie użyć ostatniego polecenia w powłoce bash. A potem jest !$ponowne użycie ostatniej części ostatniego polecenia.

np. przejrzyj jakiś plik

less path/to/your/file.txt

Jeśli chcesz teraz edytować ten sam plik, możesz użyć, !$aby uzyskać tylko ścieżkę do pliku z ostatniego polecenia

vim !$
Teshan Shanuka J
źródło
1
Ach, miałem nadzieję to znaleźć. Jak to działa z dwoma argumentami?
Jonathan
Po prostu użyje ostatniego argumentu. $touch f1 f2a następnie $vim !$oceni do$vim f2
Teshan Shanuka J