Różnice między wybraną wersją a wersją aktualną.
| Nowa wersja | Poprzednia wersja | ||
|
so:shell_constructs [2023/05/15 13:07] jkonczak utworzono |
so:shell_constructs [2025/05/19 15:58] (aktualna) jkonczak [read] |
||
|---|---|---|---|
| Linia 39: | Linia 39: | ||
| ~~Zadanie.#~~ Wpisz do pliku ''//plik//'' kolejno: | ~~Zadanie.#~~ Wpisz do pliku ''//plik//'' kolejno: | ||
| - | \\ • ''#!/bin/ls -la'' | + | <html><div style="margin-top:-1.4em"></div></html> |
| - | \\ • ''#!/usr/bin/bat'' | + | * ''#!/bin/ls -la'' |
| - | \\ • ''#!/usr/bin/env cowsay'' | + | * ''#!/usr/bin/bat'' |
| - | \\ • ''#!/bin/rm'' | + | * ''#!/usr/bin/env cowsay'' |
| - | \\ Nadaj uprawnienia wykonania dla ''//plik//''u i wykonaj go (z każdym kolejnym | + | * ''#!/bin/rm'' |
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| + | Nadaj uprawnienia wykonania dla ''//plik//''u i wykonaj go (z każdym kolejnym | ||
| shebangiem). | shebangiem). | ||
| Linia 61: | Linia 63: | ||
| Komentarze zaczynają się od ''#'' (znajdującego się poza cudzysłowami, | Komentarze zaczynają się od ''#'' (znajdującego się poza cudzysłowami, | ||
| niepoprzedzonego odwróconym ukośnikiem, etc.). | niepoprzedzonego odwróconym ukośnikiem, etc.). | ||
| - | |||
| - | <code bash> | ||
| - | # to jest komentarz | ||
| - | echo to nie jest komentarz # a to już jest | ||
| - | echo to \# "też # nie jest" ${0#bash} komentarz | ||
| - | </code> | ||
| <html> | <html> | ||
| Linia 78: | Linia 74: | ||
| ===== Parametry pozycyjne (argumenty) i specjalne ===== | ===== Parametry pozycyjne (argumenty) i specjalne ===== | ||
| - | [[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05|Parametry]] | + | [[https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_05|Parametry]] |
| to (omawiane wcześniej) zmienne oraz parametry pozycyjne i specjalne. | to (omawiane wcześniej) zmienne oraz parametry pozycyjne i specjalne. | ||
| \\ | \\ | ||
| Linia 91: | Linia 87: | ||
| Do pierwszych dziewięciu można odnosić się przez: | Do pierwszych dziewięciu można odnosić się przez: | ||
| \\ | \\ | ||
| - | **''$0'', ''$1'', ''$2'', ..., ''$9''** | + | **''$1'', ''$2'', ..., ''$9''** |
| \\ | \\ | ||
| kolejne muszą używać notacji z nawiasami wąsatymi: | kolejne muszą używać notacji z nawiasami wąsatymi: | ||
| \\ | \\ | ||
| - | ''${0}'', ''${1}'', ''${2}'', …, ''${9}'', **''${10}'', ''${11}'', ''${12}'', …, ''${42}'', …** | + | ''${1}'', ''${2}'', …, ''${9}'', **''${10}'', ''${11}'', ''${12}'', …, ''${42}'', …** |
| ++++ Przykłady | | ++++ Przykłady | | ||
| Linia 113: | Linia 109: | ||
| ++++ | ++++ | ||
| - | Komendą **''[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#shift|shift]]''** | + | Komendą **''[[https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#shift|shift]]''** |
| można usunąć pierwszy parametr i zmniejszyć pozostałym numery o jeden. | można usunąć pierwszy parametr i zmniejszyć pozostałym numery o jeden. | ||
| Linia 124: | Linia 120: | ||
| Odnoszące się do parametry pozycyjnych: | Odnoszące się do parametry pozycyjnych: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| | **''$#''** | ilość parametrów pozycyjnych | | | **''$#''** | ilość parametrów pozycyjnych | | ||
| | ''$*'' \\ ''$@'' | parametry pozycyjne poddane dzieleniu na tokeny | | | ''$*'' \\ ''$@'' | parametry pozycyjne poddane dzieleniu na tokeny | | ||
| Linia 153: | Linia 150: | ||
| Pozostałe: | Pozostałe: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| | **''$0''** | w skrypcie nazwa uruchamianego skryptu; w innym razie nazwa powłoki | | | **''$0''** | w skrypcie nazwa uruchamianego skryptu; w innym razie nazwa powłoki | | ||
| | **''$$''** | identyfikator procesu powłoki | | | **''$$''** | identyfikator procesu powłoki | | ||
| Linia 188: | Linia 186: | ||
| ~~Zadanie.#~~ | ~~Zadanie.#~~ | ||
| Napisz skrypt który wyświetli w kolejnych liniach: | Napisz skrypt który wyświetli w kolejnych liniach: | ||
| - | \\ • wartość parametru ''$0'', | + | <html><div style="margin-top:-1.4em"></div></html> |
| - | \\ • swój PID, | + | * wartość parametru ''$0'', |
| - | \\ • ilość argumentów, | + | * swój PID, |
| - | \\ • listę argumentów. | + | * ilość argumentów, |
| + | * listę argumentów. | ||
| ~~Zadanie.#~~ | ~~Zadanie.#~~ | ||
| Linia 211: | Linia 210: | ||
| Instrukcja warunkowa ma składnię: | Instrukcja warunkowa ma składnię: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <html><pre style="margin:0"> | <html><pre style="margin:0"> | ||
| <b>if</b> <i>polecenie1</i> | <b>if</b> <i>polecenie1</i> | ||
| Linia 227: | Linia 227: | ||
| Gałęzie ''elif'' i ''else'' są opcjonalne, ''elif'' może pojawiać się | Gałęzie ''elif'' i ''else'' są opcjonalne, ''elif'' może pojawiać się | ||
| wielokrotnie. | wielokrotnie. | ||
| + | |||
| + | Żadna gałąź nie może zostać pusta; jeżeli potrzebna jest gałąź bez | ||
| + | instrukcji, można wstawić w nią komendę | ||
| + | **''[[https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_17|:]]''** | ||
| + | lub ''[[https://pubs.opengroup.org/onlinepubs/9799919799/utilities/true.html|true]]''. | ||
| Przykład bez używania znaków nowej linii: | Przykład bez używania znaków nowej linii: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <code bash> | <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 | 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 | ||
| Linia 275: | Linia 281: | ||
| |''[ "$X" -gt "$Y" ]''|liczba ''"$X"'' jest większa ''"$Y"''| | |''[ "$X" -gt "$Y" ]''|liczba ''"$X"'' jest większa ''"$Y"''| | ||
| |''[ "$X" -ge "$Y" ]''|liczba ''"$X"'' jest większa bądź równa ''"$Y"''| | |''[ "$X" -ge "$Y" ]''|liczba ''"$X"'' jest większa bądź równa ''"$Y"''| | ||
| + | |||
| + | Uwaga: komenda ''test'' wykonująca porównanie arytmetyczne kończy się błędem | ||
| + | jeżeli którykolwiek z argumentów nie jest liczbą. \\ | ||
| + | <small> | ||
| + | Dlatego np. użycie do sprawdzenia argumentów | ||
| + | ''if [ "$1" -gt "$2" ]; then exit 1; fi'' da inny efekt niż | ||
| + | ''if ! [ "$1" -le "$2" ]; then exit 1; fi'' – dla argumentów będących liczbą obie | ||
| + | wersje działają tak samo, ale pierwsza przepuści też argumenty niebędące liczbą. | ||
| + | Zważ że ''!'' neguje komendę, a nie porównanie. | ||
| + | </small> | ||
| === Testy plików (wybór) === | === Testy plików (wybór) === | ||
| Linia 296: | Linia 312: | ||
| Przykład: | Przykład: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <code bash> | <code bash> | ||
| test \( -z "$X" -o "$X" -le 4 \) -a ! -s "$Y" -a \( "$Z" -le 2 -o "$Z" -ge 12 \) | test \( -z "$X" -o "$X" -le 4 \) -a ! -s "$Y" -a \( "$Z" -le 2 -o "$Z" -ge 12 \) | ||
| Linia 371: | Linia 388: | ||
| Instrukcja wyboru ma składnię: | Instrukcja wyboru ma składnię: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <html><pre style="margin:0"> | <html><pre style="margin:0"> | ||
| <b>case</b> <i>wartość</i> <b>in</b> | <b>case</b> <i>wartość</i> <b>in</b> | ||
| Linia 389: | Linia 407: | ||
| Przykład bez używania znaków nowej linii: | Przykład bez używania znaków nowej linii: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <code bash> | <code bash> | ||
| case $(LANG= date "+%A") in Monday) echo "Ugh...";; S*day) tput bel; echo "Weekend!";; *) echo "a day.";; esac | case $(LANG= date "+%A") in Monday) echo "Ugh...";; S*day) tput bel; echo "Weekend!";; *) echo "a day.";; esac | ||
| Linia 396: | Linia 415: | ||
| Napisz skrypt który sprawdzi rozszerzenie pliku (podanego jako argument) i jeśli | Napisz skrypt który sprawdzi rozszerzenie pliku (podanego jako argument) i jeśli | ||
| plik ma rozszerzenie: | plik ma rozszerzenie: | ||
| - | \\ • ''pdf'' to wykona ''pdftotext //plik// -'', | + | <html><div style="margin-top:-1.4em"></div></html> |
| - | \\ • ''zip'' to wykona ''unzip -l //plik//'', | + | * ''pdf'' to wykona ''pdftotext //plik// -'', |
| - | \\ • jakiekolwiek inne, to wykona ''cat //plik//''. | + | * ''zip'' to wykona ''unzip -l //plik//'', |
| + | * jakiekolwiek inne, to wykona ''cat //plik//''. | ||
| Linia 411: | Linia 431: | ||
| Pętla ''for'' ma składnię: | Pętla ''for'' ma składnię: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <html><pre style="margin:0"> | <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>for</b> <i>zmienna</i> <b>in</b> <i>wartość1</i> <i>wartość2</i> <i>…</i> | ||
| Linia 428: | Linia 449: | ||
| ''for NUM in $(seq -w 001 3)'' → ''for NUM in 001 002 003'' \\ | ''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 USERNAME in $(getent passwd | cut -f1 -d:)'' → ''for USERNAME in root student ...'' \\ | ||
| + | ''for FILE in "$DIR"/*'' → ''for FILE in 'my dir/file 1' 'my dir/file 2' 'my dir/subdir%%'%%'' \\ | ||
| ''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.)) | ''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: | Przykład bez używania znaków nowej linii: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <code bash> | <code bash> | ||
| for X in {1..3}; do echo -n "Przebieg $X: "; date +%N; done | for X in {1..3}; do echo -n "Przebieg $X: "; date +%N; done | ||
| Linia 447: | Linia 470: | ||
| Bash wspiera też składnię ''for'' wyglądającą i działającą jak w C: | Bash wspiera też składnię ''for'' wyglądającą i działającą jak w C: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <html><pre style="margin:0"> | <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>for ((</b><i>i=0</i><b>;</b> <i>i<5</i><b>;</b> </i>i++</i><b>))</b> | ||
| Linia 455: | Linia 479: | ||
| Przykład bez używania znaków nowej linii: | Przykład bez używania znaków nowej linii: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <code bash> | <code bash> | ||
| for ((i=3;i<=15;i+=3)); do for ((j=0;j<i;j++)); do echo -n '*'; done; echo; done | for ((i=3;i<=15;i+=3)); do for ((j=0;j<i;j++)); do echo -n '*'; done; echo; done | ||
| Linia 480: | Linia 505: | ||
| Przykład bez używania znaków nowej linii: | Przykład bez używania znaków nowej linii: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <code bash> | <code bash> | ||
| X=7; until [ $X -eq 1 ]; do [ $((X%2)) -eq 1 ] && X=$((3*X+1)) || X=$((X/2)); echo $X; done | X=7; until [ $X -eq 1 ]; do [ $((X%2)) -eq 1 ] && X=$((3*X+1)) || X=$((X/2)); echo $X; done | ||
| Linia 497: | Linia 523: | ||
| Komenda | Komenda | ||
| - | ''**[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html|read]]** | + | ''**[[https://pubs.opengroup.org/onlinepubs/9799919799/utilities/read.html|read]]** |
| [//zmienna//]...'' wczytuje jedną linię ze standardowego wejścia, a następnie: | [//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, | * (rozszerzenie Basha) jeżeli nie ma argumentów, ''read'' wpisuje linię do zmiennej REPLY, | ||
| Linia 535: | Linia 561: | ||
| ... | ... | ||
| done | done | ||
| - | </code> 1. ''polecenie'' jest wykonywane współbieżnie z pętlą \\ 2. wyniki polecenia mogą mieć spacje w linii |<code bash> | + | </code> 1. ''polecenie'' jest wykonywane współbieżnie z pętlą \\ 2. wyniki polecenia mogą mieć spacje w linii \\ <html><small>Uwaga: tylko jedna z komend z potoku (domyślnie pierwsza) działa <br> pierwszoplanowo, przez co przypisania zmiennych wewnątrz pętli <br> (działającej w tle) nie będą widoczne dalej w skrypcie</small><div style="margin-top: -1.4em"></div></html>|<code bash> |
| while read X Y | while read X Y | ||
| do | do | ||
| Linia 556: | Linia 582: | ||
| wczytanych liczb. | wczytanych liczb. | ||
| + | ~~Zadanie.#~~ | ||
| + | Napisz skrypt który odczytuje ze standardowego wejścia linie złożone z dwóch | ||
| + | liczb i po przeczytaniu każdej linii wypisuje iloczyn liczb z tej linii. | ||
| + | Skrypt ma działać do czasu aż odczytywanie z wejścia nie napotka końca pliku. | ||
| ==== select – rozszerzenie Basha ==== | ==== 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: | __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><div style="margin-top:-1.4em"></div></html> | ||
| <html><pre> | <html><pre> | ||
| <b>select</b> <i>ZMIENNA</i> <b>in</b> <i>wartość1</i> <i>wartość2</i> <i>…</i> | <b>select</b> <i>ZMIENNA</i> <b>in</b> <i>wartość1</i> <i>wartość2</i> <i>…</i> | ||
| Linia 566: | Linia 597: | ||
| </pre></html> | </pre></html> | ||
| Ta pętla: | Ta pętla: | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| - wyświetla numerowaną listę wartości, | - wyświetla numerowaną listę wartości, | ||
| - czeka na wpisanie linii wejścia przez użytkownika, | - czeka na wpisanie linii wejścia przez użytkownika, | ||
| Linia 575: | Linia 607: | ||
| ~~Zadanie.#~~ | ~~Zadanie.#~~ | ||
| Przeanalizuj i przetestuj poniższy kod. Zmień go tak, by dopiero wpisanie ''q'' przerywało pętlę. | Przeanalizuj i przetestuj poniższy kod. Zmień go tak, by dopiero wpisanie ''q'' przerywało pętlę. | ||
| + | <html><div style="margin-top:-1.4em"></div></html> | ||
| <code bash> | <code bash> | ||
| select FILE in /etc/logrotate.d/* | select FILE in /etc/logrotate.d/* | ||