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
»
shell_constructs
so:shell_constructs
Ta strona jest tylko do odczytu. Możesz wyświetlić źródła tej strony ale nie możesz ich zmienić.
===== Wykonywanie poleceń z pliku ===== ==== Tryb (nie)interaktywnym ==== Powłoka uruchomiona bez argumentów działa w **trybie interaktywnym**. \\ Powłoka uruchomiona z nazwą pliku jako argumentem działa w **trybie nieinteraktywnym**. W trybie interaktywnym powłoka czyta polecenia ze standardowego wejścia, w trybie nieinteraktywnym z podanego pliku. \\ W trybie nieinteraktywnym powłoka nie wypisuje na ekran znaku zachęty i niektórych komunikatów diagnostycznych. ~~Zadanie.#~~ Umieść w pliku ''//plik//'' w osobnych liniach polecenie ''echo hello world'' oraz polecenie ''date''. Wykonaj ''sh //plik//''. ~~Zadanie.#~~ Umieść w pliku ''//plik//'' polecenie ''readlink /proc/$$/exe''. Ustaw uprawnienia wykonywania dla tego pliku (np. ''chmod +x //plik//''). Wykonaj ten plik przez ''.%%/%%//plik//''. Potem uruchom inną powłokę (np. ''csh'' lub ''zsh'') i znów wykonaj ''.%%/%%//plik//''. Jaka powłoka wykonuje domyślnie skrypty? ==== Shebang ==== Jeżeli pierwsza linia pliku ''//plik//'' zaczyna się od ''**#!**//prog//'', to uruchamiając ''//plik// //arg//...'' zostanie wykonane ''//prog// //plik// //arg//...''. \\ Taka pierwsza linia ma nazwę [[https://pl.wikipedia.org/wiki/Shebang|shebang]] (i jest respektowana zarówno przez powłoki, jak i np. jądro Linuksa). \\ **Shebang musi zaczynać się od pełnej ścieżki do pliku wykonywalnego** i powinien móc zawierać opcje. \\ Jeśli plik ''//plik//'' zaczyna się od ''#!//prog// //a1//...'', to wykonanie ''//plik// //a2//...'' uruchomi ''//prog// //a1//... //plik// //a2//...''. ~~Zadanie.#~~ Wpisz do pliku ''//plik//'' kolejno: \\ • ''#!/bin/ls -la'' \\ • ''#!/usr/bin/bat'' \\ • ''#!/usr/bin/env cowsay'' \\ • ''#!/bin/rm'' \\ Nadaj uprawnienia wykonania dla ''//plik//''u i wykonaj go (z każdym kolejnym shebangiem). Skrypty powłoki zawierają zwykle shebang **''#!/bin/sh''** (lub ''#!/bin/bash'', jeśli skrypt korzysta z rozszerzeń Basha) i tradycyjnie nadaje im się rozszerzenie **''.sh''**. \\ W wielu językach skryptowych tradycyjnie używa się shebanga (np. python, perl, ruby). ~~Zadanie.#~~ Napisz skrypt ''hello_world.sh'' który po uruchomieniu wypisze na ekranie ''hello world''. ===== Komentarze w skryptach ===== Komentarze zaczynają się od ''#'' (znajdującego się poza cudzysłowami, niepoprzedzonego odwróconym ukośnikiem, etc.). <html> <pre class="code bash"> <span class="co0"># to jest komentarz</span> <span class="kw3">echo</span> to nie jest komentarz <span class="co0"># a to już jest</span> <span class="kw3">echo</span> to \# "też # nie jest" ${0#bash} komentarz </pre> </html> ===== Parametry pozycyjne (argumenty) i specjalne ===== [[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05|Parametry]] to (omawiane wcześniej) zmienne oraz parametry pozycyjne i specjalne. \\ Parametry pozycyjne i specjalne można rozumieć jako specjalne zmienne które można tylko odczytywać i których nazwy zaczynają się od czegoś innego niż litera bądź podkreślnik. ==== Parametry pozycyjne ==== Parametry pozycyjne to argumenty wykonania skryptu lub funkcji. Do pierwszych dziewięciu można odnosić się przez: \\ **''$0'', ''$1'', ''$2'', ..., ''$9''** \\ kolejne muszą używać notacji z nawiasami wąsatymi: \\ ''${0}'', ''${1}'', ''${2}'', …, ''${9}'', **''${10}'', ''${11}'', ''${12}'', …, ''${42}'', …** ++++ Przykłady | <html><pre style="line-height:1em"> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> cat script.sh #!/bin/sh function funkcja(){ echo $1 $3 $2 } echo $1 $3 $2 funkcja sierotka ma rysia <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> ./script.sh ala ma kota ala kota ma sierotka rysia ma <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> </pre></html> ++++ Komendą **''[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#shift|shift]]''** można usunąć pierwszy parametr i zmniejszyć pozostałym numery o jeden. [[https://www.gnu.org/software/bash/manual/html_node/Positional-Parameters.html|Dokumentacja Basha]] ~~Zadanie.#~~ Napisz skrypt który wyświetli drugi i czwarty argument. ==== Parametry specjalne ==== Odnoszące się do parametry pozycyjnych: | **''$#''** | ilość parametrów pozycyjnych | | ''$*'' \\ ''$@'' | parametry pozycyjne poddane dzieleniu na tokeny | | ''"$*"'' | parametry pozycyjne sklejone w jeden token | | **''"$@"''** | parametry pozycyjne, każdy osobnym tokenem | ++++ Przykłady | <html><pre style="line-height:1em"> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> bash -s "the_first_argument" "the second argument" <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo $# 2 <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> ls $* ls: nie ma dostępu do 'the_first_argument': Nie ma takiego pliku ani katalogu ls: nie ma dostępu do 'the': Nie ma takiego pliku ani katalogu ls: nie ma dostępu do 'second': Nie ma takiego pliku ani katalogu ls: nie ma dostępu do 'argument': Nie ma takiego pliku ani katalogu <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> ls $@ ls: nie ma dostępu do 'the_first_argument': Nie ma takiego pliku ani katalogu ls: nie ma dostępu do 'the': Nie ma takiego pliku ani katalogu ls: nie ma dostępu do 'second': Nie ma takiego pliku ani katalogu ls: nie ma dostępu do 'argument': Nie ma takiego pliku ani katalogu <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> ls "$*" ls: nie ma dostępu do 'the_first_argument the second argument': Nie ma takiego pliku ani katalogu <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> ls "$@" ls: nie ma dostępu do 'the_first_argument': Nie ma takiego pliku ani katalogu ls: nie ma dostępu do 'the second argument': Nie ma takiego pliku ani katalogu </pre></html> ++++ Pozostałe: | **''$0''** | w skrypcie nazwa uruchamianego skryptu; w innym razie nazwa powłoki | | **''$$''** | identyfikator procesu powłoki | | **''$?''** | kod wyjścia ostatnio uruchomionej komendy | | **''$!''** | identyfikator ostatnio przeniesionego w tło procesu | | ''$-'' | ustawione opcje powłoki (patrz: ''man set'') | ++++ Przykłady | <html><pre style="line-height:1em"> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> sleep 1m & [1] 21738 <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> sleep 1s <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo $! 21738 <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo $? 0 <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> false <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo $? 1 <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> python <<< 'exit(123)' <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo $? 123 <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo $$ 21731 <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> ps PID TTY TIME CMD 21731 pts/9 00:00:00 bash 21738 pts/9 00:00:00 sleep 21742 pts/9 00:00:00 ps </pre></html> ++++ [[https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html|Dokumentacja Basha]] ~~Zadanie.#~~ Napisz skrypt który wyświetli w kolejnych liniach: \\ • wartość parametru ''$0'', \\ • swój PID, \\ • ilość argumentów, \\ • listę argumentów. ~~Zadanie.#~~ Uruchom skrypt z poprzedniego zadania podając w różny sposób ścieżkę do niego. <small> ~~Zadanie.#~~ Wykorzystując komendę ''readlink -f'' lub ''realpath'' (które dostając jako argument ścieżkę do pliku zwracają jego bezwzględną ścieżkę po rozwinięciu symlinków) napisz skrypt który wyświetli ścieżkę do katalogu w którym się znajduje. </small> ===== Wyrażenia warunkowe i pętle ===== [[https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html|Dokumentacja Basha]] ==== if ==== Instrukcja warunkowa ma składnię: <html><pre style="margin:0"> <b>if</b> <i>polecenie1</i> <b>then</b> kod wykonany jeśli <i>polecenie1</i> zwróciło prawdę (wartość 0) <b>elif</b> <i>polecenie2</i> <b>then</b> kod wykonany jeśli <i>polecenie2</i> zwróciło prawdę <b>else</b> kod wykonany jeśli <i>polecenie1</i> i <i>polecenie2</i> nie zwróciło prawdy <b>fi</b> </pre></html> Instrukcje ''if'' i ''elif'' sprawdzają wartość **zwracaną** przez polecenie (a nie tekst wypisywany na standardowe wyjście czy wartość zmiennej). \\ Gałęzie ''elif'' i ''else'' są opcjonalne, ''elif'' może pojawiać się wielokrotnie. Przykład bez używania znaków nowej linii: <code bash> if grep -q ^user: /etc/passwd; then echo "'user' present"; elif grep -q ^student: /etc/passwd; then echo "'user' absent, 'student' present"; else echo "neither present"; fi </code> ~~Zadanie.#~~ Napisz skrypt który spróbuje usunąć plik o nazwie ''plik'' i jeśli usunięcie pliku się powiedzie, to wyświetli napis ''udało się'', a jeśli nie to wyświetli ''nie udało się''. ~~Zadanie.#~~ Zmień skrypt tak, by zamiast pliku o nazwie ''plik'' usuwał plik podany jako argument skryptu. ==== test ==== Polecenie **''test''** pozwala wykonywać m. inn. porównania zmiennych czy sprawdzać istnienie / rodzaj pliku. \\ Poza nazwą ''test'' to polecenie można wywołać przez **''[''**. \\ Jedyna różnica między ''test'' i **''[''** polega na tym, że używając ''['' trzeba dodać na koniec '']''. \\ Np. ''test "ala" != "ala"'' jest identyczne z ''[ "ala" != "ala" ]''. === Testy łańcuchów znaków === ^ Wyrażenie ^ Kiedy prawdziwe ^ |''[ "$X" ]'' \\ ''[ -n "$X" ]''| ''"$X"'' ma niezerową długość | |''[ -z "$X" ]''| ''"$X"'' jest puste (ma zerową długość) | |''[ "$X" = "$Y" ]''|Łańcuchy tekstu ''"$X"'' i ''"$Y"'' są identyczne | |''[ "$X" != "$Y" ]''|Łańcuchy tekstu ''"$X"'' i ''"$Y"'' są różne | Uwaga, pułapka: wyrażenie <del>''[ $X = $Y ]''</del> będzie działać jeśli ''$X'' i ''$Y'' rozwiną się każde do jednego słowa, ale jeśli któreś będzie puste bądź będzie zawierać spację, to spowoduje błąd składniowy. === Testy arytmetyczne === ^ Wyrażenie ^ Kiedy prawdziwe ^ |''[ "$X" -eq "$Y" ]''|liczba ''"$X"'' jest równa ''"$Y"''| |''[ "$X" -ne "$Y" ]''|liczba ''"$X"'' jest różna ''"$Y"''| |''[ "$X" -lt "$Y" ]''|liczba ''"$X"'' jest mniejsza ''"$Y"''| |''[ "$X" -le "$Y" ]''|liczba ''"$X"'' jest mniejsza bądź równa ''"$Y"''| |''[ "$X" -gt "$Y" ]''|liczba ''"$X"'' jest większa ''"$Y"''| |''[ "$X" -ge "$Y" ]''|liczba ''"$X"'' jest większa bądź równa ''"$Y"''| === Testy plików (wybór) === ^ Wyrażenie ^ Prawdziwe kiedy plik ''"$X"'' istnieje i… ^ |''[ -e "$X" ]''| (po prostu istnieje) | |''[ -s "$X" ]''|nie jest pusty | |''[ -f "$X" ]'' \\ ''[ -d "$X" ]'' \\ … | jest zwykłym plikiem \\ jest katalogiem \\ … | |''[ -r "$X" ]'' \\ ''[ -w "$X" ]'' \\ ''[ -x "$X" ]''|użytkownik może odczytywać plik \\ użytkownik może zapisywać do pliku \\ użytkownik może wykonywać plik | === Negowanie, grupowanie=== ''**!** //arg//'' neguje //arg//. \\ ''//arg1// **-a** //arg2//'' oznacza //arg1// oraz //arg2// \\ ''//arg1// **-o** //arg2//'' oznacza //arg1// lub //arg2// \\ nawiasy okrągłe ''( … )'' pozwalają grupować, ale trzeba je escape'ować żeby bash nie traktował ich jako znaki specjalne. Przykład: <code bash> test \( -z "$X" -o "$X" -le 4 \) -a ! -s "$Y" -a \( "$Z" -le 2 -o "$Z" -ge 12 \) </code> === Zadania === ~~Zadanie.#~~ Napisz skrypt który sprawdzi czy został wywołany z dokładnie z dwoma argumentami i czy pierwszy z nich jest (arytmetycznie) mniejszy od drugiego. Jeśli nie, wyświetl właściwy komunikat o błędzie i wyjdź ze skryptu (komendą ''exit''). ~~Zadanie.#~~ Napisz skrypt który sprawdzi czy pierwszy argument jest zwykłym plikiem do którego bieżący użytkownik ma prawa zapisu. Jeśli nie, wyświetl odpowiedni komunikat i wyjdź. Jeśli tak, dopisz bieżącą datę do tego pliku. ~~Zadanie.#~~ Napisz skrypt który sprawdzi czy pierwsza linia pliku (podanego jako argument) ma treść ''#!/bin/sh'' i czy plik jest wykonywalny. Jeśli tak jest, wyświetl ''//nazwa pliku// jest wykonywalnym skryptem powłoki''. <small> ~~Zadanie.#~~ Zmodyfikuj powyższy skrypt tak, by w razie potrzeby nadawał prawa dostępu i dopisywał shebang do wskazanego pliku. </small> ==== [[ … ]] i (( … )) – rozszerzenie Basha ==== Bash wprowadza dwie dodatkowe konstrukcji powłoki do testów / porównań: * ''%%[[%% … ]]'' jako konstrukcja działająca jak ulepszone polecenie ''test'', * ''%%((%% … ))'' do arytmetyki. Wyrażenie arytmetyczne wewnątrz ''%%((%% … ))'' jest wyliczane i jeśli zwróci 0, to ''%%((%% … ))'' zwraca fałsz, w przeciwnym razie prawdę. \\ Wewnątrz ''%%((%% … ))'' można używać m. inn. operatorów ''=='',''!='', ''<'', ''<='', ''>'', ''>='' i ''… ? … : …''. Działanie ''%%[[%% … ]]'' jest dość złożone. Ponad to co umie komenda ''['', wyrażenie w podwójnych kwadratowych nawiasach: * ''['' dzieli wyniki podstawień na słowa, ''%%[[%%'' zostawia je bez zmian, ++przykład|<html><pre style="margin:0;line-height:1em"> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> X="1 -eq 2" <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> [ $X ] && echo T || echo F F <span style="font-style:italic;color:gray;"># wykona porównanie 1 z 2 </span> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> [ "$X" ] && echo T || echo F T <span style="font-style:italic;color:gray;"># sprawdzi czy ciąg znaków '1 -eq 2' jest niepusty</span> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> [[ $X ]] && echo T || echo F T <span style="font-style:italic;color:gray;"># sprawdzi czy ciąg znaków '1 -eq 2' jest niepusty</span> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> [[ "$X" ]] && echo T || echo F T <span style="font-style:italic;color:gray;"># sprawdzi czy ciąg znaków '1 -eq 2' jest niepusty</span> </pre></html>++ * wewnątrz ''%%[[%%'' **nie** są wykonywane dopasowania do nazw plików, ++przykład|<html><pre style="margin:0;line-height:1em"> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> [[ *.txt ]] && echo T || echo F T <span style="font-style:italic;color:gray;"># sprawdzi czy ciąg znaków '*.txt' jest niepusty</span> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> [ *.txt ] && echo T || echo F -bash: [: nums.txt: oczekiwano operatora jednoargumentowego F <span style="font-style:italic;color:gray;"># bash podstawił nazwy plików '*.txt', więc [ dostało złe argumenty</span> </pre></html>++ * Operator ''='' i ''!='' dopasowują tekst do wzorca, a nie porównują teksty, ++przykład|<html><pre style="margin:0;line-height:1em"> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> [ abc.log = *.log ] && echo T || echo F F <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> [[ abc.log = *.log ]] && echo T || echo F T <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> </pre></html>++ * Dodano operator ''=~'' dopasowujący do wyrażenia regularnego, ++przykład|<html><pre style="margin:0;line-height:1em"> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> [[ abc.txt =~ ^a.*\.txt$ ]] && echo T || echo F T </pre></html>++ * Operatory ''-a'' i ''-o'' zastąpiono przez ''&&'' i ''||'', a nawiasów okrągłych nie trzeba escape'ować, np:\\ ''if %%[[%% -f file && ( ! -s file || ! -w file ) ]]; then echo "'file' exists and is not empty or not writeable"; fi'' ==== case ==== Instrukcja wyboru ma składnię: <html><pre style="margin:0"> <b>case</b> <i>wartość</i> <b>in</b> <i>wzorzec1</i><b>)</b> <i>polecenia1</i> <b>;;</b> <i>wzorzec2</i><b>)</b> <i>polecenia2</i> <b>;;</b> <i>*</i><b>)</b> <i>polecenia3</i> <b>;;</b> <b>esac</b> </pre></html> //Wartość// jest kolejno dopasowywana do //wzorzec1//, //wzorzec2//, … i przy znalezieniu pierwszego dopasowania wykonywane są odpowiednie polecenia. Dalsze dopasowania nie są brane pod uwagę. \\ Polecenia są dowolnym ciągiem poleceń zakończonym **'';;''**((Bash rozszerza składnię o '';&'' które przechodzi do komend z kolejnego wzorca i '';;&'' które dopasowuje kolejne wzorce.)). \\ Nie ma specjalnej składni na domyślne dopasowanie – używa się po prostu wzorca ''*''. Przykład bez używania znaków nowej linii: <code bash> case $(LANG= date "+%A") in Monday) echo "Ugh...";; S*day) tput bel; echo "Weekend!";; *) echo "a day.";; esac </code> ~~Zadanie.#~~ Napisz skrypt który sprawdzi rozszerzenie pliku (podanego jako argument) i jeśli plik ma rozszerzenie: \\ • ''pdf'' to wykona ''pdftotext //plik// -'', \\ • ''zip'' to wykona ''unzip -l //plik//'', \\ • jakiekolwiek inne, to wykona ''cat //plik//''. ===== Pętle ===== [[https://www.gnu.org/software/bash/manual/html_node/Looping-Constructs.html|Dokumentacja Basha]] We wszystkich pętlach działają słowa kluczowe **''break''** i **''continue''** do, odpowiednio, wyjścia poza pętlę i rozpoczęcia następnego przebiegu pętli. ==== for ==== Pętla ''for'' ma składnię: <html><pre style="margin:0"> <b>for</b> <i>zmienna</i> <b>in</b> <i>wartość1</i> <i>wartość2</i> <i>…</i> <b>do</b> <i>polecenia</i> <b>done</b> </pre></html> W kolejnych przebiegach pętli kolejne //wartości// z listy są przypisywane do zmiennej //zmienna//. Po wyjściu z pętli //zmienna// ma ostatnią z przypisanych w pętli wartości. \\ <small>Pominięcie ''in //wartość1// //wartość2// …'' spowoduje przyjęcie za listę wartości ''"$@"''.</small> Często w miejsce listy wartości podaje się podstawienie które jest rozkładane na wiele wartości, np: \\ ''for NUM in {1..3} {7..9}'' → ''for NUM in 1 2 3 7 8 9'' \\ ''for NUM in $(seq -w 001 3)'' → ''for NUM in 001 002 003'' \\ ''for USERNAME in $(getent passwd | cut -f1 -d:)'' → ''for USERNAME in root student ...'' \\ ''for FILE in $(grep -il 'ldap' /etc/*.conf 2>/dev/null)'' → ''for FILE in /etc/autofs.conf /etc/ldap.conf ...''((Uwaga na spacje w nazwach plików! Ta wersja nie jest na nie odporna.)) Przykład bez używania znaków nowej linii: <code bash> for X in {1..3}; do echo -n "Przebieg $X: "; date +%N; done </code> ~~Zadanie.#~~ Napisz skrypt, który dla każdego pliku podanego jako argument wyświetli: jego nazwę, jego pierwszą linię i jego ostatnią linię. ~~Zadanie.#~~ Napisz pętlę która wyświetli wszystkie potęgi dwójki o wykładnikach od 1 do wybranej wartości. \\ (Wartość potęgi można wyliczyć np. wyrażeniem ''$%%((2**%%//wykładnik//))''.) ==== for – rozszerzenie Basha ==== Bash wspiera też składnię ''for'' wyglądającą i działającą jak w C: <html><pre style="margin:0"> <b>for ((</b><i>i=0</i><b>;</b> <i>i<5</i><b>;</b> </i>i++</i><b>))</b> <b>do</b> <i>polecenia</i> <b>done</b> </pre></html> Przykład bez używania znaków nowej linii: <code bash> for ((i=3;i<=15;i+=3)); do for ((j=0;j<i;j++)); do echo -n '*'; done; echo; done </code> ==== while i until ==== <html><p style="margin:0">Pętla ''while'' ma składnię:</p><pre style="margin:0"> <b>while</b> <i>polecenie1</i> <b>do</b> <i>polecenia2</i> <b>done</b> </pre></html> Bliźniacza pętla ''until'' ma składnię: <html><pre style="margin:0"> <b>until</b> <i>polecenie1</i> <b>do</b> <i>polecenia2</i> <b>done</b> </pre></html> Pętla ''while'' wykonuje //''polecenia2''// do momentu aż //''polecenie1''// zwraca prawdę. \\ Pętla ''until'' wykonuje //''polecenia2''// do momentu aż //''polecenie1''// zwraca fałsz. Przykład bez używania znaków nowej linii: <code bash> X=7; until [ $X -eq 1 ]; do [ $((X%2)) -eq 1 ] && X=$((3*X+1)) || X=$((X/2)); echo $X; done </code> ~~Zadanie.#~~ Napisz pętlę która wyświetli wszystkie potęgi dwójki mniejsze niż podana liczba. ~~Zadanie.#~~ Napisz skrypt który utworzy nowy plik ''myProg_//NUM//.log'' o najniższej możliwej wartości ''//NUM//'', a następnie przypisze jego nazwę do zmiennej ''LOG'' i umieści w tym pliku bieżącą datę. ===== Wczytywanie wartości podawanych przez użytkownika ===== ==== read ==== Komenda ''**[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html|read]]** [//zmienna//]...'' wczytuje jedną linię ze standardowego wejścia, a następnie: * (rozszerzenie Basha) jeżeli nie ma argumentów, ''read'' wpisuje linię do zmiennej REPLY, * ''read'' dzieli wczytaną linię na słowa, * każdej kolejnej zmiennej (podanej w liście argumentów) przypisuje kolejne słowo, * jeśli słów jest mniej niż zmiennych, pozostałe zmienne są ustawiane na pustą wartość, * jeśli słów jest więcej niż zmiennych, pozostałe słowa są doklejane do ostatniej zmiennej. ++++ Przykład | <html><pre style="line-height:1em"> <span style="font-weight:bold;color:#7f7f7f;"></span> <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> read X Y Z jeden "dwa trzy" <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo "X='$X' Y='$Y' Z='$Z'" X='jeden' Y='"dwa' Z='trzy"' <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> read X Y Z jeden <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo "X='$X' Y='$Y' Z='$Z'" X='jeden' Y='' Z='' <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> read X Y Z jeden dwa trzy cztery pięć <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo "X='$X' Y='$Y' Z='$Z'" X='jeden' Y='dwa' Z='trzy cztery pięć' <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> read jeden dwa trzy cztery pięć <span style="font-weight:bold;color:#7f7f7f;"></span><span style="font-weight:bold;color:#00ff00;">user@host</span><span style="font-weight:bold;color:#5c5cff;"> ~ $</span> echo "'$REPLY'" ' jeden dwa trzy cztery pięć' </pre></html> ++++ <html><div style=""></html> <small> |Komenda ''read'' jest często wykorzystywana we wzorcach:|| |<code bash> polecenie | while read X do ... done </code> 1. ''polecenie'' jest wykonywane współbieżnie z pętlą \\ 2. wyniki polecenia mogą mieć spacje w linii |<code bash> while read X Y do ... done << EOF wartoscX1 wartoscY1 wartoscX2 wartoscY2 EOF </code> ustawia się po parę/trójkę/… zmiennych naraz| | Do poprawnego działania należy zapewnić żeby nic we wnętrzu pętli nie czytało ze standardowego wejścia|| </small> ~~Zadanie.#~~ Napisz skrypt który dopisuje do pliku o nazwie ''//log//'' linię tekstu wczytaną ze standardowego wejścia poprzedzoną bieżącą datą. ~~Zadanie.#~~ Napisz skrypt który wczytuje liczby (znajdujące się w osobnych liniach) do momentu aż nie pojawi się pusta linia i następnie wyświetla najmniejszą z wczytanych liczb. ==== select – rozszerzenie Basha ==== __Pętla__ ''[[https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html#index-select|select]]'' ma składnię identyczną jak pętla for: <html><pre> <b>select</b> <i>ZMIENNA</i> <b>in</b> <i>wartość1</i> <i>wartość2</i> <i>…</i> <b>do</b> <i>polecenia</i> <b>done</b> </pre></html> Ta pętla: - wyświetla numerowaną listę wartości, - czeka na wpisanie linii wejścia przez użytkownika, - przeczytaną linię przypisuje zmiennej ''REPLY'' - jeśli linia jest jednym z numerów, do ''//ZMIENNA//'' przypisuje odpowiadającą ''//wartość//…'' - wykonuje ''//polecenia//'' - wraca do kroku 2 ~~Zadanie.#~~ Przeanalizuj i przetestuj poniższy kod. Zmień go tak, by dopiero wpisanie ''q'' przerywało pętlę. <code bash> select FILE in /etc/logrotate.d/* do [[ $FILE ]] || continue echo "===$FILE===" cat "$FILE" break done </code> ~~META: language = pl ~~
so/shell_constructs.1684155874.txt.gz
· ostatnio zmienione: 2023/05/15 15:04 przez
jkonczak
Narzędzia strony
Pokaż stronę
Poprzednie wersje
Odnośniki
Złóż / rozłóż wszystko
Do góry