przejście do zawartości
Jan Kończak
Narzędzia użytkownika
Zaloguj
Narzędzia witryny
Narzędzia
Pokaż stronę
Poprzednie wersje
Odnośniki
Ostatnie zmiany
Menadżer multimediów
Indeks
Zaloguj
Ostatnie zmiany
Menadżer multimediów
Indeks
Jesteś tutaj:
start
»
so
»
funkcje_trap_xargs
so:funkcje_trap_xargs
Ta strona jest tylko do odczytu. Możesz wyświetlić źródła tej strony ale nie możesz ich zmienić.
===== Funkcje w powłoce ===== ==== POSIX shell ==== Aby zdefiniować [[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_05|funkcję]] w powłoce, należy użyć składni ''**//nazwa//() //treść//**'', gdzie //treść// powinna być [[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_04|złożoną komendą]] (np. ciągiem poleceń zamkniętych w ''{ … }''). \\ Wywołanie takiej funkcji realizuje się przez ''//nazwa// [//argument//]...'', przy czym wewnątrz funkcji zmienne ''$#'' oraz ''$1'', ''$2'', ... dotyczą właśnie //argument//ów funkcji. Wewnątrz funkcji można też używać polecenia ''return [//n//]'' które kończy funkcję zwracając wartość //n// lub, jeśli nie podano //n//, wartość ''$?''. Dla funkcji //nazwa// polecenie ''type //nazwa//'' zwróci przynajmniej informację że //nazwa// jest funkcją, a w Bashu dodatkowo wyświetli jej ciało (podobnie jak komenda ''declare -f //nazwa//''). <html><div style="line-height:1em"><p>Przykład:</p><pre style="margin: 0 0 -1em 0"><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> colorEcho() { > case "$1" in > red) CCODE=31;; > green) CCODE=32;; > blue) CCODE=34;; > *) CCODE=5;; > esac > echo -ne "\033[${CCODE}m"; > echo -n "$2"; > echo -e "\033[0m"; > } <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> colorEcho red riding hood <span style="color:#cd0000;">riding </span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> colorEcho green "anne of green gables" <span style="color:#00cd00;">anne of green gables</span> </pre> </html> ++++ Wynik type colorEcho | <html> <pre><span style="font-weight:bold;color:#7f7f7f;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> type colorEcho colorEcho jest funkcją colorEcho () { case "$1" in red) CCODE=31 ;; green) CCODE=32 ;; blue) CCODE=34 ;; *) CCODE=5 ;; esac; echo -ne "\033[${CCODE}m"; echo -n "$2"; echo -e "\033[0m" } <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> </pre></html> ++++ <html></div></html> Inny przykład: <code bash> compressInDateDir() { [ $# -ge 2 ] || return 1 TARNAME="$(readlink -f "$1")" shift WORKDIR="$(mktemp -dp. || mktemp -d)" [ "$WORKDIR" ] || return 1 DATE=$(date +%Y_%m_%d) mkdir "$WORKDIR/$DATE" cp -al "$@" "$WORKDIR/$DATE" tar cJf "$TARNAME" -C "$WORKDIR" "$DATE" rm -rf "$WORKDIR" } </code> ==== Bash ==== Powłoka Bash wprowadza parę rozszerzeń do funkcji. \\ Po pierwsze, w Bashu można poprzedzić funkcję słowem kluczowym ''function''.\\ Po drugie, **w Bashu można deklarować lokalne zmienne wewnątrz funkcji poprzedzając ich nazwę słowem kluczowym ''local''**.<html> <pre style="line-height:1em"> <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> X=5; <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> up() { X=$((X+$1)); echo $X; } <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> up 1 6 <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> up 1 7 <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> up() { local X=$((X+$1)); echo $X; } <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> up 1 8 <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> up 1 8 <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo $X 7 </pre></html> ==== Ćwiczenia ==== ~~Zadanie.#~~ Napisz funkcję która wyświetla ''hello world''. ~~Zadanie.#~~ Napisz funkcję przyjmującą dwa argumenty: liczbę (ilość powtórzeń) i tekst. Funkcja ma wypisać na standardowe wyjście podany tekst podaną ilość razy. ~~Zadanie.#~~ Napisz funkcję przyjmującą jako argument nazwę pliku. Jeśli taki plik nie istnieje, w wyniku działania funkcji taki plik ma zostać utworzony bez praw dostępu dla grupy i pozostałych. \\ Możesz użyć polecenia ''umask'' (lepsze rozwiązanie) lub ''chmod'' (gorsze rozwiązanie). ~~Zadanie.#~~ Napisz funkcję zastępującą program ''tree'': funkcja ma przeszukać w głąb (DFS) pliki zaczynając od podanego katalogu i wypisać dla każdego pliku jego nazwę z odpowiednimi wcięciami. <small> ~~Zadanie.#~~ Napisz funkcję liczącą rekurencyjne silnię i wypisującą jej wynik na standardowe wyjście. </small> ===== Obsługa sygnałów ===== Komendą ''[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_28|trap]] //polecenie// //SYGNAŁ//'' można ustawić obsługę podanego //SYGNAŁ//u oraz, podając zamiast nazwy sygnału słowo EXIT, ustawić polecenie do wykonania bezpośrednio przed zakończeniem procesu powłoki. \\ **W powłoce obsługa sygnału ustawiona komendą ''trap'' jest wykonywana bezpośrednio po zakończeniu polecenia w trakcie którego odebrano sygnał.** \\ Polecenie musi być podane jako ciąg tekstu. \\ Polecenie ustawione jako EXIT nie jest wykonywane tylko jeśli powłoka kończy pracę w wyniku sygnału KILL lub polecenia ''exec''. \\ Składnia ''trap - //SYGNAŁ//'' przywraca domyślną obsługę sygnału. ~~Zadanie.#~~ Dodaj obsługę sygnału INT (generowanego przez ''Ctrl+c'') do skryptu wykonującego ''sleep //czas//'' oraz ''echo //tekst//''. Porównaj przerwanie komendy ''sleep'' sygnałem INT z przerwaniem skryptu sygnałem INT. ~~Zadanie.#~~ Stwórz w skrypcie plik tymczasowy komendą ''mktemp''. Ustaw obsługę zdarzenia wyjścia z powłoki tak, by usuwała ten plik i wyświetlała tekst. Umieść w skrypcie komendę ''sleep //czas//'' oraz ''echo //tekst//''. \\ • Porównaj przerwanie komendy ''sleep'' sygnałem INT z przerwaniem skryptu sygnałem INT \\ • Sprawdź czy przerwanie skryptu sygnałem TERM usuwa plik. \\ • Sprawdź czy przerwanie skryptu sygnałem KILL usuwa plik. ===== To co nie trafiło gdzie indziej ===== === source === Komenda ''[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_18|.]] //plik//'' (i komenda ''source //plik//'' w Bashu) uruchamiają polecenia z podanego pliku w bieżącej powłoce (tzn. tak jakby były wpisane z klawiatury). ~~Zadanie.#~~ Wpisz do pliku //plik// ustawienie wartości kilku zmiennym. Wczytaj ten plik komendą ''.'' (lub ''source'') i sprawdź wartości tych zmiennych. ~~Zadanie.#~~ Wpisz do pliku //plik// polecenie ''exit''. Nadaj mu prawa do wykonywania. Wykonaj ten plik (tzn. wykonaj ''./plik'') oraz użyj komendy ''.'' na tym pliku (tzn. wykonaj ''. ./plik''). === eval i exec === Komenda ''[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_19|eval]]'' wykonuje podaną jako tekst komendę. Komenda ''[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_20|exec]]'' zawierająca tylko przekierowania ustawia podane przekierowania dla powłoki (było przy okazji przekierowań), natomiast z podaną komendą zastępuje powłokę podanym poleceniem. ~~Zadanie.#~~ Umieść w skrypcie ''eval xterm'' oraz ''echo eval'' i uruchom ten skrypt. \\ Następnie umieść w skrypcie ''exec xterm'' oraz ''echo exec'' i uruchom ten skrypt. === yes === Komenda ''yes [//tekst//]'' wypisuje w kółko //tekst// na standardowe wyjście. Domyślnie wypisuje tekst ''y''. \\ ''yes'' jest używane do generowania odpowiedzi dla programów które pytają ''czy na pewno chcesz...'' i nie mają przełącznika który wyłącza takie pytania. ~~Zadanie.#~~ Stwórz pliki ''//plik_1//'', ''//plik_2//'', … , ''//plik_9//''. Spróbuj je usunąć komendą ''rm -i plik_?''. Połącz tą komendę z komendą ''yes'' tak żeby ''yes'' potwierdził usunięcie plików. === basename i dirname === Program ''[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html#tag_20_07|basename]] //ścieżka// [//rozszerzenie//]'' wypisuje na standardowe wyjście nazwę pliku wskazanego ścieżką, opcjonalnie usuwając z nazwy //rozszerzenie//. Program ''[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html#tag_20_35|dirname]] //ścieżka//'' wypisuje na standardowe wyjście katalog w którym znajduje się plik wskazany ścieżką. ''$(basename "$//X//")'' i ''$(dirname "$//X//")'' w wielu przypadkach można zastąpić przez ''${//X//##*/}'' i ''${//X//%/*}''. Należy pamiętać, że ''basename'' i ''dirname'', w odróżnieniu od podstawień, poradzą sobie ze zniekształconymi ścieżkami. ~~Zadanie.#~~ Przetestuj ''basename'' i ''dirname'' dla: \\ • ''../../../etc/passwd'' \\ • ''/usr/share/icons/hicolor/'' \\ • ''plik'' === fc === Komenda ''[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/fc.html#tag_20_44|fc]]'' tworzy plik tymczasowy, wstawia do niego poprzednią komendę z historii, otwiera ten plik w edytorze tekstu, a po zamknięciu edytora wykonuje poprawioną komendę. ~~Zadanie.#~~ Wykonaj jakąś długą komendę (np. ''for X in $(grep -lR 'terminal' /usr/share/applications/); do grep "Name" $X; done''), następnie wpisz ''fc'', zmodyfikuj ją i wykonaj. ===== Tablice w Bashu [extra] ===== Poza zwykłymi zmiennymi, powłoka Bash wspiera zwykłe tablice (indeksowane kolejnymi liczbami naturalnymi) oraz tablice asocjacyjne (indeksowane tekstowymi kluczami). Skrócony opis poniżej; pełen w [[https://www.gnu.org/software/bash/manual/html_node/Arrays.html|podręczniku Basha]]. ==== Zwykłe ==== Zwykłą tablicę o nazwie ''//TABLICA//'' tworzy się przez: * komendę: ''declare -a TABLICA'' * przypisanie pustej tablicy: ''TABLICA=()'' * przypisanie tablicy z zawartością: ''TABLICA=(//wartość0// [//wartość1//]...)'' * ustawienie wartości elementu tablicy: ''TABLICA[//0//]=//wartość//'' Dodanie nowych elementów pod wskazany indeks realizuje się komendą ''TABLICA[//indeks//]=//wartość//'', natomiast dodanie na koniec komendą ''TABLICA+=(//wartość1// [//wartość2//]...)''. Odwołanie się do zmiennej //TABLICA// spowoduje: * ''$TABLICA'' podstawi wartość elementu pod indeksem 0 * ''${TABLICA[//indeks//]}'' podstawi wartość elementu pod indeksem //indeks// * ''${TABLICA[@]}'' podstawi wszystkie wartości w tablicy * ''${!TABLICA[@]}'' podstawi wszystkie indeksy w tablicy * ''${#TABLICA[@]}'' podstawi ilość elementów ==== Asocjacyjne ==== Asocjacyjną tablicę o nazwie ''//TABLICA//'' tworzy się przez komendę ''declare -A TABLICA''. Dodanie nowych elementów można wykonywać przez: * ''TABLICA[//klucz//]=//wartość//'' * ''TABLICA+=([klucz1]=wartość1 [klucz2]=wartość2 ...)'' (uwaga: tutaj ''['' są elementem składni) * ''TABLICA+=(klucz1 wartość1 klucz2 wartość2 ...)'' Przy czym dwie ostatnie składnie, przy zastąpieniu ''+='' przez ''='', służą do nadpisania tablicy podaną listą kluczy i wartości. Odwoływanie się do tablicy asocjacyjnej jest identyczne jak dla zwykłej. ===== xargs i parallel ===== ==== xargs ==== Program ''**[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/xargs.html#tag_20_158|xargs]]** //program//'' czyta ze standardowego wejścia kolejne nazwy i wykonuje ''//program//'' z tymi nazwami jako argumentem. \\ ''xargs'' jest głównie wykorzystywany w potokach, do uruchomienia podanego programu z listą argumentów generowanych przez potok. <small> Poglądowo, np. ''potok | xargs program'' wykonuje mniej więcej ''program $(potok)'', natomiast np. ''potok | xargs -n1 program'' wykonuje mniej więcej ''for ARG in $(potok); do program $ARG; done'', ale potok i program są wywoływane jednocześnie. </small> Domyślnie ''xargs //program//'' wykonuje //program// wpisując na koniec listy argumentów wszystkie przeczytane nazwy naraz. \\ Można określić po ile argumentów naraz ma być wstawianych na koniec podanej komendy przełącznikiem ''-n'': <html><pre style="line-height:1em"><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> seq 5 | xargs echo -e 1 2 3 4 5 <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> seq 5 | xargs -n 2 echo -e 1 2 3 4 5 </pre></html> Można też użyć przełącznika ''-I //słowo//'' do wskazania w które miejsce linii poleceń ma być wstawiony każdy argument (co implikuje uruchomienie komendy osobno dla każdego argumentu): <html><pre style="line-height:1em"><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> seq 3 | xargs -I ARG echo ">>ARG<< >>ARG<<" >>1<< >>1<< >>2<< >>2<< >>3<< >>3<< </pre></html> Polecenie ''xargs'' rozdziela standardowe wejście po dowolnych białych znakach, co powoduje problemy np. ze spacjami. \\ Większość implementacji polecenia ''xargs'' rozumie przełącznik ''-0'' rozdzielający nazwy znakiem ''\0'': <html><pre style="line-height:1em"> <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> fortune BOFH Excuse #443: Zombie processes detected, machine is haunted. <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> fortune | xargs -n1 echo " *" * BOFH * Excuse * #443: * Zombie * processes * detected, * machine * is * haunted. <span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> fortune | tr '\n' '\0' | xargs -n1 -0 echo " *" * BOFH Excuse #443: * Zombie processes detected, * machine is haunted. </pre></html> Przykładowe przełączniki dla różnych programów generujące znak ''\0'' do oddzielenia kolejnych elementów opisuje nawet [[https://en.wikipedia.org/wiki/Xargs#Separator_problem|Wikipedia dla hasła xargs]]. [[https://www.gnu.org/software/findutils/manual/html_node/find_html/xargs-options.html|GNU xargs]] (zwykle domyślny w Linuksie) rozumie też przełącznik ''-P [//num//]'' który pozwala uruchomić //num// równoległych procesów (jeśli podano ''-P'' bez argumentów, odpalane jest tyle procesów z ilu rdzeni można skorzystać). ~~Zadanie.#~~ Stwórz katalogi o nazwach ''001'', ''002'', ''003'', ..., ''999'' używając ''xargs''. ~~Zadanie.#~~ Policz sumy kontrolne MD5 dla plików ''*.pdf'' znalezionych narzędziem ''locate'' w katalogu ''/usr/share/''. \\ Wykonaj to zadanie zarówno używając ''xargs'' jak i używając pętli w powłoce. ~~Zadanie.#~~ Skopiuj pliki z katalogu ''/usr/include'' zawierające tekst ''typedef signed char'' do katalogu ''/tmp/'' używając xargs. \\ Komenda ''grep'' z przełącznikiem ''-l'' wypisuje tylko nazwy pasujących plików, a z przełącznikiem ''-R'' szuka rekurencyjnie. ==== GNU parallel [ekstra] ==== Do uruchamiania współbieżnie m. inn. programu dla argumentów czytanych ze standardowego wejścia można też wykorzystać program [[https://en.wikipedia.org/wiki/GNU_parallel|parallel]]. Dla tego zastosowania jest praktycznie zamiennikiem ''xargs''. \\ Z odpowiednimi argumentami ''parallel'' pozwala też uruchamiać dowolne zadania współbieżnie kontrolując ilość jednocześnie uruchomionych zadań. \\ Więcej informacji na [[https://www.gnu.org/software/parallel/|gnu.org/software/parallel]]. ~~META: language = pl ~~
so/funkcje_trap_xargs.1685356033.txt.gz
· ostatnio zmienione: 2023/05/29 12:27 przez
jkonczak
Narzędzia strony
Pokaż stronę
Poprzednie wersje
Odnośniki
Złóż / rozłóż wszystko
Do góry