Manipulacja zawartościa zmiennych

Zapis i odczyt wartości zmiennej

Przypisanie zmiennej i jej wyświetlenie - więcej w rozdziale dotyczacym inicjalizacji wartości zmiennej.

johny@ThinkPad:~$ ETYKIETA="wartosc_zmiennej"
johny@ThinkPad:~$ $ETYKIETA
wartosc_zmiennej: command not found
johny@ThinkPad:~$ echo "$ETYKIETA"
wartosc_zmiennej
johny@ThinkPad:~$ echo "${ETYKIETA}"
wartosc_zmiennej

Sposoby quotowania zmiennych

johny@ThinkPad:~$ ETYKIETA="wartosc_zmiennej"
johny@ThinkPad:~$ echo '${ETYKIETA}'
${ETYKIETA}
johny@ThinkPad:~$ echo "${ETYKIETA}"
wartosc_zmiennej
johny@ThinkPad:~$

Odwołanie pośrednie do zmiennej

  • ${!var} - Odwołanie pośrednie pozwala nam na odwołanie się do zmiennej która jest tworzona dynamicznie.
johny@ThinkPad:~$ ETYKIETA="wartosc_zmiennej"
johny@ThinkPad:~$ wartosc_zmiennej="ukryta_wartosc_zmiennej"
johny@ThinkPad:~$ echo "${!ETYKIETA}"
ukryta_wartosc_zmiennej
johny@ThinkPad:~$

Podpowiedź

Jest to rzadko wykorzystywana funkcja, utrudnia pisanie skryptów łatwych w późniejszym utrzymaniu.

Modyfikacja wielkości liter w zmiennej napisowej

  • ${var,}, ${var,pattern} - zmień pierwszą literę na małą,
  • ${var,,}, ${var,,pattern} - zmień wszystkie litery na małe,
  • ${var^}, ${var^pattern} - zmień pierwszą literę na dużą,
  • ${var^^}, ${var^^pattern} - zmień wszystkie litery na duże.
Operacja Przykład

Zamiana na duże litery

  • ${ZMIENNA^} - pierwszej litery
  • ${ZMIENNA^^} - wszystkich liter
johny@ThinkPad:~$ ETYKIETA="wArToSc zMiEnNeJ"
johny@ThinkPad:~$ echo "${ETYKIETA^}"
WArToSc zMiEnNeJ
johny@ThinkPad:~$ echo "${ETYKIETA^^}"
WARTOSC ZMIENNEJ

Podpowiedź

Wiele osób do wykonania takiej czynności stosuje zewnętrzne polecenie tr, które jest na ogół sporo wolniejsze.

johny@ThinkPad:~$ ETYKIETA="wArToSc zMiEnNeJ"
johny@ThinkPad:~$ echo "$ETYKIETA" | tr '[:lower:]' '[:upper:]'
WARTOSC ZMIENNEJ
johny@ThinkPad:~$ echo "$ETYKIETA" | tr '[a-z]' '[A-Z]'
WARTOSC ZMIENNEJ

Zamiana na małe litery

  • ${ZMIENNA,} - pierwszej litery
  • ${ZMIENNA,,} - wszystkich liter
johny@ThinkPad:~$ ETYKIETA="wArToSc zMiEnNeJ"
johny@ThinkPad:~$ echo "${ETYKIETA,}"
wArToSc zMiEnNeJ
johny@ThinkPad:~$ echo "${ETYKIETA,,}"
wartosc zmiennej

Podpowiedź

Wiele osób do wykonania takiej czynności stosuje zewnętrzne polecenie tr, które jest na ogół sporo wolniejsze.

johny@ThinkPad:~$ ETYKIETA="wArToSc zMiEnNeJ"
johny@ThinkPad:~$ echo "$ETYKIETA" | tr '[:upper:]' '[:lower:]'
wartosc zmiennej
johny@ThinkPad:~$ echo "$ETYKIETA" | tr '[A-Z]' '[a-z]'
wartosc zmiennej

Zamiana wielkości liter (małe na duże, duże na małe)

  • ${ZMIENNA~} - pierwszej litery
  • ${ZMIENNA~~} - wszystkich liter
johny@ThinkPad:~$ ETYKIETA="wArToSc zMiEnNeJ"
johny@ThinkPad:~$ echo "${ETYKIETA~}"
WArToSc zMiEnNeJ
johny@ThinkPad:~$ echo "${ETYKIETA~~}"
WaRtOsC ZmIeNnEj

Podpowiedź

Wiele osób do wykonania takiej czynności stosuje zewnętrzne polecenie tr, które jest na ogół sporo wolniejsze.

johny@ThinkPad:~$ ETYKIETA="wArToSc zMiEnNeJ"
johny@ThinkPad:~$ echo "$ETYKIETA" | tr '[:upper:][:lower:]' '[:lower:][:upper:]'
WaRtOsC ZmIeNnEj
johny@ThinkPad:~$ echo "$ETYKIETA" | tr '[a-zA-Z]' '[A-Za-z]'
WaRtOsC ZmIeNnEj

Dopełnienie nazwy zmiennej (variable name expansion)

Podpowiedź

Sposób znajdywania/dopełnienia/dopasowania zmiennej jest bardzo ciekawy, jednakże nie spotkałem się jeszcze z praktycznym wykorzystaniem tej funkcji w Bash.

Dopełnianie wszystkich nazwy zmiennych, które rozpoczynają się od podanego PATTERN, zmienne wypisywane są od siebie odseparowane poprzez zmienną specjalną IFS. Kiedy zostanie uzyty @ wynik dopełnienia pojawia się zaquotowany jako osobna etykieta, ekażda zmienna jest dopełniania do osobnego słowa.

  • ${!PATTERN*}
  • ${!PATTERN@}
johny@ThinkPad:~$ ETYKIETA="wartosc_zmiennej"
johny@ThinkPad:~$ ETYKIETA_2="wartosc_zmiennej2"
johny@ThinkPad:~$ ETYKIETA_NOWA="wartosc_zmiennej_nowa"
johny@ThinkPad:~$ echo "${!ETYKIETA*}"
ETYKIETA ETYKIETA_2 ETYKIETA_NOWA
johny@ThinkPad:~$ echo ${!ETYKIETA@}
ETYKIETA ETYKIETA_2 ETYKIETA_NOWA

Usuwaine podciągów znaków (używane do manipulowania nazwami plików)

${ETYKIETA#PATTERN} - usunięcie z początku najkrótszego łancucha pasującego do PATTERN
johny@ThinkPad:~$ ETYKIETA='/home/johny/example.txt.gz'
johny@ThinkPad:~$ echo "${ETYKIETA#*.}"
txt.gz
${ETYKIETA##PATTERN} - usunięcie z początku najdłuższego łańcucha pasującego do PATTERN
johny@ThinkPad:~$ ETYKIETA='/home/johny/example.txt.gz'
johny@ThinkPad:~$ echo "${ETYKIETA##*.}"
gz
${ETYKIETA%PATTERN} - usunięcie z końca najkrótszego łancucha pasującego do PATTERN
johny@ThinkPad:~$ ETYKIETA='/home/johny/example.txt.gz'
johny@ThinkPad:~$ echo "${ETYKIETA%/*}"
/home/johny

Załóżmy, że mamy w katalogu pliki o rozszerzeniu JPEG i chcemy zmienić im rozszerzenie jpg - możemy posłużyć się poniższym skryptem.

for f in *.JPEG ; do
    mv "$f" "${f%.JPEG}.jpg"
done
${ETYKIETA%%PATTERN} - usunięcie z końca najdłuższego łancucha pasującego do PATTERN
johny@ThinkPad:~$ ETYKIETA='/home/johny/example.txt.gz'
johny@ThinkPad:~$ echo "${ETYKIETA%%.*}"
/home/johny/example

Podpowiedź

Funkcja podstawień czasami jest wykorzystywane w skryptach, jednak niektórzy programiści korzystają z polecenia basename, które jest dla większości przypadków wolniejsze.

Znajdź i zamień

${ETYKIETA/PATTERN/STRING}, ${ETYKIETA/PATTERN} - zamiana pierwszego wystąpienia ciągu znaków na inny
johny@ThinkPad:~$ ETYKIETA='/home/johny/examples/example.txt.gz'
johny@ThinkPad:~$ echo "${ETYKIETA/example/n01}"
/home/johny/n01s/example.txt.gz
johny@ThinkPad:~$ echo "${ETYKIETA/example}"
/home/johny/s/example.txt.gz
${ETYKIETA//PATTERN/STRING}, ${ETYKIETA//PATTERN} - - zamiana wszystkich wystąpień ciągu znaków na inny
johny@ThinkPad:~$ ETYKIETA='/home/johny/examples/example.txt.gz'
johny@ThinkPad:~$ echo "${ETYKIETA//example/n01}"
/home/johny/n01s/n01.txt.gz
johny@ThinkPad:~$ echo "${ETYKIETA//example}"
/home/johny/s/.txt.gz

Podpowiedź

Uzycie modyfikatora # (${ETYKIETA/#PATTERN/STRING}) powoduje podmianę łancucha znaków tylko gdy dopasowanie jest na początku łancucha znaków.

johny@ThinkPad:~$ ETYKIETA='/home/johny/examples/example.txt.gz'
johny@ThinkPad:~$ echo "${ETYKIETA/#example/n01}"
/home/johny/examples/example.txt.gz
johny@ThinkPad:~$ ETYKIETA='example/home/johny/examples/example.txt.gz'
johny@ThinkPad:~$ echo "${ETYKIETA/#example/n01}"
n01/home/johny/examples/example.txt.gz

Podpowiedź

Uzycie modyfikatora % (${ETYKIETA/%PATTERN/STRING}) powoduje podmianę łancucha znaków tylko gdy dopasowanie jest na końcu łancucha znaków.

johny@ThinkPad:~$ ETYKIETA='/home/johny/examples/example.txt.gz'
johny@ThinkPad:~$ echo "${ETYKIETA/%example/n01}"
/home/johny/examples/example.txt.gz
johny@ThinkPad:~$ ETYKIETA='/home/johny/examples/example.txt.gz.example'
johny@ThinkPad:~$ echo "${ETYKIETA/%example/n01}"
/home/johny/examples/example.txt.gz.n01

Podpowiedź

Czy są inne modyfikatory? Tak są jeżeli włączymy shellopt extglob.

?(pattern-list)
       Matches zero or one occurrence of the given patterns
*(pattern-list)
       Matches zero or more occurrences of the given patterns
+(pattern-list)
       Matches one or more occurrences of the given patterns
@(pattern-list)
       Matches one of the given patterns
!(pattern-list)
       Matches anything except one of the given patterns

Ostrzeżenie

Często do wykonania takich operacji używa się skomplikownych narzędzi lub nawet całych języków programowania ukrytych pod poleceniami sed, awk, perl. W większości przypadków jest to wolniejsze rozwiązanie niż skorzystanie z implementacji w Bash.

Długość zmiennej (ciagu znaków)

${#ETYKIETA} - określ długość ciągu znaku

johny@ThinkPad:~$ ETYKIETA='/home/johny/example.txt.gz'
johny@ThinkPad:~$ echo "${#ETYKIETA}"
26
johny@ThinkPad:~$ ZMIENNA=10
johny@ThinkPad:~$ echo "${#ZMIENNA}"
2

Wycinanie podnapisów ze zmiennej

Składnia: ${ETYKIETA:OFFSET}, ${ETYKIETA:OFFSET:LENGTH}

johny@ThinkPad:~$ ETYKIETA="ala_ma_kota"
johny@ThinkPad:~$ echo ${ETYKIETA:4}
ma_kota
johny@ThinkPad:~$ echo ${ETYKIETA:0:3}
ala
johny@ThinkPad:~$ echo ${ETYKIETA:0:-5}
ala_ma

Używanie domyślnej wartości

Składnia: ${ETYKIETA:-WORD}, ${ETYKIETA-WORD}

Najpierw musimy usunąć zmienną ETYKIETA możemy to zrobić za pomocą komendy unset.

johny@ThinkPad:~$ unset ETYKIETA
johny@ThinkPad:~$ echo $ETYKIETA

johny@ThinkPad:~$

Przykład

johny@ThinkPad:~$ echo "${ETYKIETA:-DOMYSLNA_WARTOSC}"
DOMYSLNA_WARTOSC
johny@ThinkPad:~$ echo $ETYKIETA

johny@ThinkPad:~$ echo "${ETYKIETA-DOMYSLNA_WARTOSC}"
DOMYSLNA_WARTOSC
johny@ThinkPad:~$ echo $ETYKIETA

johny@ThinkPad:~$

Przypisanie domyślnej wartości do zmiennej

Składnia: ${ETYKIETA:=WORD}, ${ETYKIETA=WORD}

Najpierw musimy usunąć zmienną ETYKIETA możemy to zrobić za pomocą komendy unset.

johny@ThinkPad:~$ unset ETYKIETA
johny@ThinkPad:~$ echo $ETYKIETA

johny@ThinkPad:~$

Przykład

johny@ThinkPad:~$ echo "$ETYKIETA"

johny@ThinkPad:~$ A="${ETYKIETA:=DOMYSLNA_WARTOSC}"
johny@ThinkPad:~$ echo "$ETYKIETA"
DOMYSLNA_WARTOSC
johny@ThinkPad:~$ echo "$A"
DOMYSLNA_WARTOSC
johny@ThinkPad:~$ echo "$ETYKIETA2"

johny@ThinkPad:~$ echo "${ETYKIETA2=DOMYSLNA_WARTOSC}"
DOMYSLNA_WARTOSC
johny@ThinkPad:~$ echo "$ETYKIETA"
DOMYSLNA_WARTOSC

Ostrzeżenie

Przypisanie to nie jest zbyt czytelne, znacznie lepiej skorzystać z konstrukcji: ETYKIETA=”${ETYKIETA:-DOMYSLNA_WARTOSC}”, ponieważ ona wyraża intencję zmiany wartości zmiennej. w przypadku sposobu z ${ETYKIETA:=WORD}, ${ETYKIETA=WORD} na pierwszy rzut oka nie widać modyfikacji wartości zmiennej.

Użyj alternatywnej wartości zmiennej (jesli ustawiona)

Polecenie pozwala na użycie innej wartości zmiennej jeśli ta jest ustawiona / nie pusta.

Składania ${ETYKIETA:+WORD}, ${ETYKIETA+WORD}.

johny@ThinkPad:~$ unset ZMIENNA
johny@ThinkPad:~$ echo "${ZMIENNA:+NIE JEST USTAWIONA}"

johny@ThinkPad:~$ echo "${ZMIENNA:+JEST USTAWIONA}"

johny@ThinkPad:~$ unset ZMIENNA
johny@ThinkPad:~$ echo "${ZMIENNA:+JEST USTAWIONA}"

johny@ThinkPad:~$ ZMIENNA=OK
johny@ThinkPad:~$ echo "${ZMIENNA:+JEST USTAWIONA}"
JEST USTAWIONA

Więcej informacji o wykorzystaniu tej konstrukcji na:

Wyświetl błąd jeżeli zmienna jest pusta lub nieustawiona

Składnia: ${ETYKIETA:?WORD}, ${ETYKIETA?WORD}

johny@ThinkPad:~$ unset ETYKIETA
johny@ThinkPad:~$ "${ETYKIETA:?zmienna nie ustawiona}"
bash: ETYKIETA: zmienna nie ustawiona
johny@ThinkPad:~$ "${ETYKIETA:?}"
bash: ETYKIETA: parameter null or not set
johny@ThinkPad:~$ "${ETYKIETA?zmienna nie ustawiona}"
bash: ETYKIETA: zmienna nie ustawiona
johny@ThinkPad:~$ "${ETYKIETA?}"
bash: ETYKIETA: parameter null or not set