Kiedyś używałem CShell (csh), który pozwala utworzyć alias, który przyjmuje parametr. Notacja była podobna
alias junk="mv \\!* ~/.Trash"
W Bash to nie działa. Biorąc pod uwagę, że Bash ma wiele przydatnych funkcji, zakładam, że ten został zaimplementowany, ale zastanawiam się, jak to zrobić.
"$1"
ls
dols -la
, a następnie wpisującls foo bar
byłoby naprawdę wykonaćls -la foo bar
. W wierszu poleceń”alias test_args="echo PREFIX --$1-- SUFFIX"
, który wywołany za pomocątest_args ABCD
zwraca następujące dane wyjściowe konsoliPREFIX ---- SUFFIX ABCD
Odpowiedzi:
Alias Bash nie akceptuje bezpośrednio parametrów. Będziesz musiał utworzyć funkcję.
alias
nie akceptuje parametrów, ale funkcję można wywołać podobnie jak alias. Na przykład:Nawiasem mówiąc, funkcje Bash zdefiniowane w twoim
.bashrc
i innych plikach są dostępne jako polecenia w twojej powłoce. Na przykład możesz wywołać wcześniejszą funkcję w ten sposóbźródło
$1
cytaty?source
ing .bashrc doda tę funkcję, ale nie odblokuje starego aliasu. Ponieważ aliasy mają wyższy priorytet niż funkcje, spróbuje użyć aliasu. Musisz albo zamknąć i ponownie otworzyć powłokę, albo zadzwonićunalias <name>
. Być może uratuję kogoś 5 minut, które właśnie zmarnowałem.exec bash
: Uruchomi nową powłokę, dając ci czysty odczyt twoich konfiguracji, tak jakbyś zamknął i ponownie otworzył, ale zachował również ustawienia zmiennych środowiskowych tej sesji . Ponadto wykonywaniebash
bez exec może być przydatne, gdy chcesz obsługiwać myśli jak stos.mv "$1" "$1.bak"
. bez cudzysłowów, gdyby 1 $ to „hello world”, wykonałbyśmv hello world hello world.bak
zamiastmv "hello world" "hello world.bak"
.Uściślając powyższą odpowiedź, możesz uzyskać 1-liniową składnię, tak jak w przypadku aliasów, co jest wygodniejsze w przypadku definicji ad-hoc w plikach powłoki lub .bashrc:
Nie zapomnij o średniku przed zamykającym prawym wspornikiem. Podobnie w przypadku rzeczywistego pytania:
Lub:
źródło
mv "$1" "$1.bak"; cp "$2" "$1"
na,mv "$1" "$1.bak" && cp "$2" "$1"
aby nie utracić danych, gdymv
wystąpią problemy (np. Pełny system plików).Pytanie jest po prostu zadawane źle. Nie tworzysz aliasu, który przyjmuje parametry, ponieważ
alias
po prostu dodaje drugą nazwę dla czegoś, co już istnieje. Funkcjonalność, jakiej chce OP, tofunction
polecenie utworzenia nowej funkcji. Nie musisz aliasować funkcji, ponieważ funkcja ma już nazwę.Myślę, że chcesz czegoś takiego:
Otóż to! Możesz użyć parametrów 1 USD, 2 USD, 3 USD itp. Lub po prostu napełnić je wszystkie za pomocą $ @
źródło
echo -e '#!/bin/bash\nshopt -s expand_aliases\nalias asrc='\''echo "${BASH_SOURCE[0]}"'\'' # note the '\''s\nfunction fsrc(){ echo "${BASH_SOURCE[0]}";}'>>file2&&echo -e '#!/bin/bash\n. file2\nalias rl='\''readlink -f'\''\nrl $(asrc)\nrl $(fsrc)'>>file1&&chmod +x file1&&./file1;rm -f file1 file2
$@
nazwy plików ze spacjami itp.TL; DR: Zrób to zamiast tego
O wiele łatwiejsze i bardziej czytelne jest użycie funkcji niż aliasu do umieszczenia argumentów w środku polecenia.
Jeśli będziesz czytać dalej, nauczysz się rzeczy, których nie musisz wiedzieć o przetwarzaniu argumentów powłoki. Wiedza jest niebezpieczna. Po prostu uzyskaj pożądany wynik, zanim ciemna strona na zawsze kontroluje twoje przeznaczenie.
Wyjaśnienie
bash
aliasy zrobić przyjąć argumenty, ale tylko na końcu :Umieszczanie argumentów w środku polecenia
alias
jest rzeczywiście możliwe, ale robi się brzydkie.Nie próbuj tego w domu, dzieciaki!
Jeśli lubisz obchodzenie ograniczeń i robienie tego, co mówią inni, jest niemożliwe, oto przepis. Po prostu nie obwiniaj mnie, jeśli twoje włosy są zniszczone, a twoja twarz jest pokryta sadzą w stylu szalonego naukowca.
Obejściem tego problemu jest przekazanie argumentów, które
alias
akceptują tylko na końcu, do opakowania, które wstawi je na środku, a następnie wykona polecenie.Rozwiązanie 1
Jeśli naprawdę nie chcesz używać funkcji jako takiej, możesz użyć:
Można wymienić
$@
ze$1
jeśli chcesz tylko pierwszy argument.Wyjaśnienie 1
Tworzy to funkcję tymczasową
f
, do której przekazywane są argumenty (uwagaf
wywoływana na samym końcu).unset -f
Usuwa definicja funkcji jako alias jest wykonany tak, aby nie obijać się potem.Rozwiązanie 2
Możesz także użyć podpowłoki:
Wyjaśnienie 2
Alias tworzy polecenie takie jak:
Komentarze:
Element zastępczy
_
jest wymagany, ale może to być dowolny element. Ustawia się nash
„s”$0
i jest wymagane, aby pierwszy argument podany przez użytkownika nie został wykorzystany. Demonstracja:Wymagane są pojedyncze cudzysłowy wewnątrz pojedynczych cudzysłowów. Oto przykład tego, że nie działa z podwójnymi cudzysłowami:
Oto wartości interaktywna powłoka użytkownika
$0
i$@
zastępuje się podwójnie cytowany zanim zostanie przekazany dosh
. Oto dowód:Pojedyncze cudzysłowy zapewniają, że zmienne te nie są interpretowane przez interaktywną powłokę i są dosłownie przekazywane
sh -c
.Możesz użyć podwójnych cudzysłowów
\$@
, ale najlepszą praktyką jest zacytowanie argumentów (ponieważ mogą one zawierać spacje), i\"\$@\"
wygląda jeszcze brzydiej, ale może pomóc Ci wygrać konkurs zaciemniania, w którym zwariowane włosy są warunkiem wstępnym.źródło
alias gc='git checkout'
$@
? Są one niezbędne, jeśli masz np. Pliki ze spacjami.Alternatywnym rozwiązaniem jest użycie znacznika , narzędzia, które niedawno stworzyłem, które pozwala „dodawać zakładki” do szablonów poleceń i łatwo umieszczać kursor na elementach zastępczych poleceń:
Odkryłem, że przez większość czasu używam funkcji powłoki, więc nie muszę pisać często używanych poleceń w wierszu poleceń. Problem użycia funkcji w tym przypadku użycia polega na dodaniu nowych terminów do mojego słownika poleceń i konieczności pamiętania, jakie parametry funkcji odnoszą się do polecenia rzeczywistego. Celem markera jest wyeliminowanie tego obciążenia psychicznego.
źródło
Wystarczy, że utworzysz funkcję w aliasie:
Państwo musi umieścić w cudzysłowie „$ 1”, ponieważ apostrofów nie zadziała.
źródło
bash: syntax error near unexpected token '{mkdir'
.;
wewnątrz funkcji_mkcd
najprawdopodobniej z tego wynika błąd.{
i}
Oto trzy przykłady funkcji, które mam w sobie
~/.bashrc
, które są zasadniczo aliasami, które akceptują parametr:.
.
.
Bibliografia:
źródło
Alias Bash absolutnie akceptuje parametry. Właśnie dodałem alias, aby utworzyć nową aplikację reagującą, która akceptuje nazwę aplikacji jako parametr. Oto mój proces:
Otwórz profil bash do edycji w nano
Dodaj swoje aliasy, po jednym w wierszu:
Zapisz i zamknij edytor nano
Powiedz terminalowi, aby używał nowych aliasów w .bash_profile
Otóż to! Możesz teraz używać swoich nowych aliasów
źródło
Uwaga: W przypadku, gdy pomysł nie jest oczywisty, złym pomysłem jest używanie aliasów do czegokolwiek poza aliasami, z których pierwszy to „funkcja w aliasie”, a drugi to „trudne do odczytania przekierowanie / źródło”. Są też wady (które, jak sądzę , byłyby oczywiste, ale na wszelki wypadek jesteś zdezorientowany: nie mam na myśli, że można ich używać ... gdziekolwiek!)
.................................................. .................................................. ............................................
Odpowiedziałem na to wcześniej i zawsze tak było w przeszłości:
co jest w porządku i dobre, chyba że unikasz jednoczesnego korzystania z funkcji. w takim przypadku możesz skorzystać z ogromnej możliwości przekierowania tekstu przez bash:
Oba są mniej więcej tej samej długości dają lub biorą kilka znaków.
Rzeczywistym kopiący jest różnica czasu, górna jest metoda „funkcja” i dolny jest metoda „przekierowanie source”. Aby udowodnić tę teorię, czas mówi sam za siebie:
To jest dolna część około 200 wyników, wykonywanych w przypadkowych odstępach czasu. Wygląda na to, że tworzenie / niszczenie funkcji zajmuje więcej czasu niż przekierowanie. Mam nadzieję, że pomoże to przyszłym użytkownikom tego pytania (nie chciałem tego zatrzymywać dla siebie).
źródło
Jeśli szukasz ogólnego sposobu zastosowania wszystkich parametrów do funkcji, a nie tylko jednej, dwóch lub innej zakodowanej na stałe ilości, możesz to zrobić w ten sposób:
W powyższym przykładzie przekazuję wszystkie parametry od momentu uruchomienia
runjar
do aliasu.Na przykład, gdybym
runjar hi there
to zrobił , skończyłoby to faktycznie uruchomieniemjava -jar myjar.jar hi there
. Gdybymrunjar one two three
to zrobił , uruchomiłbym sięjava -jar myjar.jar one two three
.Lubię to
$@
oparte na rozwiązaniu, ponieważ działa z dowolną liczbą parametrów.źródło
runjar
zamiast uczynić ją aliasem funkcji? Wydaje się niepotrzebnie skomplikowane!alias
-ed (lub posiadające właściwości rzeczy przekazanealias
) w plikach bash? jeśli tak, to po prostu to nie wiedziałemalias runjar='java -jar myjar.jar'
. Aliasy akceptują argumenty, ale tylko na końcu.Z szacunkiem dla wszystkich, którzy mówią, że nie można wstawić parametru w środku aliasu, właśnie go przetestowałem i stwierdziłem, że zadziałał.
alias mycommand = "python3" $ 1 "script.py --folderoutput WYNIKI /"
kiedy potem uruchomiłem mycommand foobar, działało to dokładnie tak, jakbym napisał polecenie z długim czasem.
źródło
alias myalias="echo 1 "$1" 3"; myalias 2
daje mi:1 3 2
Istnieją uzasadnione techniczne powody, aby chcieć uogólnionego rozwiązania problemu aliasu bash, który nie ma mechanizmu przejmowania arbitralnych argumentów. Jednym z powodów jest to, że na polecenie, które chcesz wykonać, miałyby negatywny wpływ zmiany środowiska wynikające z wykonania funkcji. We wszystkich innych przypadkach należy korzystać z funkcji.
To, co ostatnio zmusiło mnie do podjęcia próby rozwiązania tego, to to, że chciałem stworzyć kilka skróconych poleceń do drukowania definicji zmiennych i funkcji. Więc napisałem kilka funkcji w tym celu. Istnieją jednak pewne zmienne, które są (lub mogą być) zmieniane przez samo wywołanie funkcji. Wśród nich są:
FUNCNAME BASH_SOURCE BASH_LINENO BASH_ARGC BASH_ARGV
Podstawowe polecenie, którego użyłem (w funkcji) do drukowania defns zmiennych. w postaci danych wyjściowych polecenia set:
Na przykład:
Problem: Nie spowoduje to wydrukowania wyżej wymienionych definicji zmiennych, ponieważ znajdują się one w bieżącym kontekście , np. Jeśli w interaktywnym pytaniu powłoki (lub nie w żadnym wywołaniu funkcji) FUNCNAME nie jest zdefiniowany. Ale moja funkcja mówi mi nieprawidłowe informacje:
Jedno z opracowanych przeze mnie rozwiązań zostało wspomniane przez innych w innych postach na ten temat. W tym konkretnym poleceniu wypisania zmiennych defns., Które wymaga tylko jednego argumentu, zrobiłem to:
Co daje poprawne dane wyjściowe (brak) i status wyniku (false):
Jednak nadal czułem się zmuszony do znalezienia rozwiązania, które zadziałałoby dla dowolnej liczby argumentów.
Ogólne rozwiązanie dotyczące przekazywania arbitralnych argumentów do polecenia aliasowego Bash:
Na przykład:
Zaletą tego rozwiązania jest to, że wszystkie specjalne sztuczki używane do obsługi parametrów pozycyjnych (argumentów) poleceń działają podczas tworzenia polecenia uwięzionego. Jedyną różnicą jest to, że należy użyć składni tablicy.
Na przykład,
Jeśli chcesz „$ @”, użyj „$ {CMD_ARGV [@]}”.
Jeśli chcesz „$ #”, użyj „$ {# CMD_ARGV [@]}”.
Itp.
źródło
Kiedyś zrobiłem fajny projekt i nadal go używam. Pokazuje kilka animacji podczas kopiowania plików za pomocą
cp
polecenia,cp
ponieważ nic nie pokazuje i jest to trochę frustrujące. Więc stworzyłem ten aliasA to jest skrypt spiner
Tak to wygląda
Cykliczna animacja)
źródło
Do pobierania parametrów należy używać funkcji!
Jednak $ @ zostanie zinterpretowany podczas tworzenia aliasu zamiast podczas wykonywania aliasu i ucieczka przed $ nie działa również. Jak rozwiązać ten problem?
Aby pozbyć się tego problemu, musisz użyć funkcji powłoki zamiast aliasu. Możesz zdefiniować foo w następujący sposób:
LUB
Na koniec wywołaj foo (), używając następującej składni:
Upewnij się, że dodajesz swoją foo () do
~/.bash_profile
lub~/.zshrc
pliku.W twoim przypadku to zadziała
źródło
Funkcje są rzeczywiście prawie zawsze odpowiedzią, jak już obszernie napisano i potwierdzone przez ten cytat ze strony podręcznika: „W prawie każdym celu aliasy są zastępowane przez funkcje powłoki”.
Dla kompletności i ponieważ może to być przydatne (nieznacznie lekka składnia), można zauważyć, że gdy parametr (y) podążają za aliasem, mogą być nadal używane (chociaż nie spełniałoby wymagań OP). Prawdopodobnie najłatwiej to wykazać na przykładzie:
pozwala mi pisać coś podobnego
ssh_disc myhost
, który jest rozwijany zgodnie z oczekiwaniami:ssh -O stop myhost
Może to być przydatne w przypadku poleceń, które przyjmują złożone argumenty (moja pamięć nie jest już tym, czego używa ...
źródło
Zarówno funkcje, jak i aliasy mogą wykorzystywać parametry, jak pokazali tutaj inni. Dodatkowo chciałbym zwrócić uwagę na kilka innych aspektów:
1. funkcja działa we własnym zakresie, alias dzieli zakres
Warto znać tę różnicę, gdy musisz coś ukryć lub ujawnić. Sugeruje również, że funkcja jest lepszym wyborem do enkapsulacji.
Wynik:
2. skrypt otoki jest lepszym wyborem
Kilkakrotnie zdarzyło mi się, że nie można znaleźć aliasu lub funkcji podczas logowania przez
ssh
lub przy zmianie nazwy użytkownika lub środowiska dla wielu użytkowników. Istnieją wskazówki i triki dotyczące plików kropek lub ten interesujący z aliasem:alias sd='sudo '
pozwala, aby ten kolejny aliasalias install='sd apt-get install'
działał zgodnie z oczekiwaniami (zwróć uwagę na dodatkowe miejscesd='sudo '
). Jednak w takich przypadkach skrypt opakowujący działa lepiej niż funkcja lub alias. Główną zaletą skryptu opakowującego jest to, że jest widoczny / wykonywalny pod zamierzoną ścieżką (tj. / Usr / loca / bin /), gdzie jako funkcję / alias należy uzyskać źródło, zanim będzie można go użyć. Na przykład wstawiasz funkcję do ~ / .bash_profile lub ~ / .bashrc dlabash
, ale później przełączasz na inną powłokę (tj.zsh
), to funkcja nie jest już widoczna. W razie wątpliwości skrypt opakowania jest zawsze najbardziej niezawodnym i przenośnym rozwiązaniem.źródło
source
w funkcji działa dobrze.f () { source /tmp/nst; }
robi dokładnie to, czego oczekuję. Może twójPATH
błąd jest niewłaściwy, więc działa źleactivate
lub coś; ale uruchamianiesource
z funkcji działa dobrze.function
słowa kluczowego w swojej definicji, patrz wiki.bash-hackers.org/scripting/obsolete -function funcname {
jest starą składnią kash bash obsługującą wsteczną kompatybilność z powłokami sprzed POSIX, podczas gdyfuncname() {
jest to oficjalna składnia standaryzowana przez POSIX.function funcname() {
to niedopasowanie tych dwóch, które nie jest kompatybilne ze starożytnym ksh lub kompatybilne z POSIX sh, i dlatego najlepiej go unikać.Oto przykład:
Bardzo ważne:
{
i przed}
.;
Po każdym poleceniu jest po kolei. Jeśli zapomnisz o tym po ostatnim poleceniu,>
zamiast tego zobaczysz monit!"$1"
źródło
Jak już zauważyli inni, korzystanie z funkcji należy uznać za najlepszą praktykę.
Oto jednak inne podejście, wykorzystujące
xargs
:Pamiętaj, że ma to skutki uboczne dotyczące przekierowywania strumieni.
źródło
Nic nie musisz robić, alias robi to automatycznie.
Na przykład, jeśli chcę sparametryzować master git pull origin, mogę po prostu utworzyć alias w następujący sposób:
a podczas wywoływania go jako parametr możesz przekazać „master” (nazwa gałęzi):
źródło