View RSS Feed

pbojczuk

Iterowanie po tablicach w Bashu

Rate this Entry
Przy okazji tego wątku na Forum, postanowiłem odświeżyć sobie działanie tablic w Bashu.

Poprosiłem użytkownika, żeby sprawdził, jakie pakiety ma zainstaloane, a jakich nie ma w ten sposób:
Code:
#!/bin/bash

RPMS=(  TESTOWY_NIE_MA_TAKIEGO_PAKIETU nie_ma cheese-lang gdm-lang gnome-contacts-lang
        gnome-control-center-color
        gnome-control-center-goa gnome-control-center-lang gnome-session-lang gnome-session-wayland
        gnome-shell-calendar gnome-shell-classic gnome-shell-extension-gpaste gnome-shell-lang
        gnome-shell-search-provider-bijiben gnome-shell-search-provider-contacts
        gnome-shell-search-provider-documents gnome-shell-search-provider-nautilus gnome-tweaks-lang
        gstreamer-plugins-bad-lang libpurple-lang libpurple-tcl pidgin pulseaudio-gdm-hooks cheese
        gnome-shell-extension-desktop-icons gnome-contacts gnome-tweaks libpurple patterns-gnome-gnome
        patterns-gnome-gnome_imaging patterns-gnome-gnome_office patterns-gnome-gnome_utilities
        libpurple-branding-openSUSE patterns-gnome-gnome_x11 gstreamer-plugins-farstream
        patterns-gnome-gnome_basic libfarstream-0_2-5 patterns-gnome-gnome_basis gdm-branding-openSUSE
        gdm gnome-shell gnome-session-default-session gnome-session gnome-control-center libcheese-gtk25
        libcheese8 gstreamer-plugins-bad
)

for i in ${RPMS[@]}; do
  rpm -q --queryformat "%{NAME}\n" $i
done
Działa, ale wynik nie jest posortowany. Dodajmy więc dwie puste tablice:
Code:
INSRPMS=()
MISRPMS=()
i poprośmy Basha, by uzupełniał je w zależności od exit code'u: jak jest 0, to paczka jest zainstalowana, a jak nie zero, to paczki nie ma:
Code:
for i in ${RPMS[@]}; do
  rpm -q --queryformat "%{NAME}\n" $i &> /dev/null
  if [ $? -eq 0 ]; then
    INSRPMS=(${INSRPMS[@]} "$i")
  else
    MISRPMS=(${MISRPMS[@]} "$i")
  fi
done
Jak tablica się wygeneruje, to można ją przeiterować, by odczytać wszystkie elementy:
Code:
echo "Not installed RPMS:"
for i in ${MISRPMS[@]}; do
  echo "  $i is not installed"
done
To też działa, ale czy da się lepiej? No da się! Dodajmy więc funkcję, której przekażemy tablicę jako dane wejściowe:
Code:
function _printArray(){
  ARRAY=("$@")
  for i in "${ARRAY[@]}"; do
    echo -e "  ${i}"
  done
}
Sprawdźmy, co obie tablice zebrały:
Code:
echo "# Installed RPMs:"
_printArray ${INSRPMS[@]}
echo -e "\n# Missing RPMs:"
_printArray ${MISRPMS[@]}
Działa dobrze, ale jakoś tak smutno. Dodajmy trochę kolorów - poprawi to również czytelność wyniku.

W osobnej sesji sprawdźmy, co się stanie, jak to przeklepiemy:
Code:
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'

echo -e "${RED}RED${NC}"
echo -e "${GREEN}GREEN${NC}"
Stosunkowo łatwo można pokolorować nasz wynik, tworząc nowe tablice z zainstalowanymi i brakującymi paczkami:
Code:
for i in ${RPMS[@]}; do
  rpm -q --queryformat "%{NAME}\n" ${i} &> /dev/null
  if [ $? -eq 0 ]; then
    INSRPMS=(${INSRPMS[@]} "${GREEN}${i}${NC}")
  else
    MISRPMS=(${MISRPMS[@]} "${RED}${i}${NC}")
  fi
done
Ma to zasadniczą wadę. Wynik na ekranie będzie, owszem, ładny, jednak tracimy możliwość dalszej obróbki nowo utworzonych tablic, bo każdy element ma taką formę:
Code:
\033[0;32mgnome-shell-lang\033[0m
Spróbujmy więc jako pierwszy element tablicy, którą przekazujemy do naszej funkcji, dodać kolor:
Code:
_printArray green ${INSRPMS[@]}
W takiej postaci pierwszym pakietem, który będzie wyszukiwany będzie nazwa koloru, dlatego poprośmy for o to, by liczył elementy w tablicy od drugiego elementu:
Code:
${ARRAY[@]:1}
Wróćmy do naszego skryptu. Obslużmy przekazany pierwszy element tablicy, czyli kolor, i połączmy wszystko:
Code:
#!/bin/bash

RPMS=(  TESTOWY_NIE_MA_TAKIEGO_PAKIETU nie_ma cheese-lang gdm-lang gnome-contacts-lang
        gnome-control-center-color
        gnome-control-center-goa gnome-control-center-lang gnome-session-lang gnome-session-wayland
        gnome-shell-calendar gnome-shell-classic gnome-shell-extension-gpaste gnome-shell-lang
        gnome-shell-search-provider-bijiben gnome-shell-search-provider-contacts
        gnome-shell-search-provider-documents gnome-shell-search-provider-nautilus gnome-tweaks-lang
        gstreamer-plugins-bad-lang libpurple-lang libpurple-tcl pidgin pulseaudio-gdm-hooks cheese
        gnome-shell-extension-desktop-icons gnome-contacts gnome-tweaks libpurple patterns-gnome-gnome
        patterns-gnome-gnome_imaging patterns-gnome-gnome_office patterns-gnome-gnome_utilities
        libpurple-branding-openSUSE patterns-gnome-gnome_x11 gstreamer-plugins-farstream
        patterns-gnome-gnome_basic libfarstream-0_2-5 patterns-gnome-gnome_basis gdm-branding-openSUSE
        gdm gnome-shell gnome-session-default-session gnome-session gnome-control-center libcheese-gtk25
        libcheese8 gstreamer-plugins-bad
)

INSRPMS=()
MISRPMS=()

GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'

function _printArray(){
  ARRAY=("$@")
  if [ $1 = "red" ]; then
    COL=$RED
  elif [ $1 = "green" ]; then
    COL=$GREEN
  fi

  for i in "${ARRAY[@]:1}"; do
    echo -e "  ${COL}${i}${NC}"
  done
}


for i in ${RPMS[@]}; do
  rpm -q --queryformat "%{NAME}\n" ${i} &> /dev/null
  if [ $? -eq 0 ]; then
    INSRPMS=(${INSRPMS[@]} "${i}")
  else
    MISRPMS=(${MISRPMS[@]} "${i}")
  fi
done

echo "Installed RPMs:"
_printArray green ${INSRPMS[@]}
echo -e "\nMissing RPMs:"
_printArray red ${MISRPMS[@]}
Przydatne linki:

Submit "Iterowanie po tablicach w Bashu" to Digg Submit "Iterowanie po tablicach w Bashu" to del.icio.us Submit "Iterowanie po tablicach w Bashu" to StumbleUpon Submit "Iterowanie po tablicach w Bashu" to Google Submit "Iterowanie po tablicach w Bashu" to Facebook Submit "Iterowanie po tablicach w Bashu" to Twitter

Updated 10-Nov-2021 at 12:43 by pbojczuk

Categories
Uncategorized

Comments