Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!
Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.
Możesz dać jakiś przykład bo nic z tego zrozumieć nie można... mi wychodzi że chcesz ifa niezależnego od warunku a to wielce dziwna konstrukcja...
Offline
już zrobiłem, zastosowałem funkcje żeby to wszystko uporządkować. chodziło mi o skrypt sprawdzający pocztę gmail. Najpierw sprawdza połączenie z netem: jeśli go nie ma to czeka 10 sekund i sprawdza ponownie, jeśli jest połacenie to sprawdza od razu pocztę.
Offline
[quote=ethanak]Możesz dać jakiś przykład bo nic z tego zrozumieć nie można... mi wychodzi że chcesz ifa niezależnego od warunku a to wielce dziwna konstrukcja...[/quote]
Chyba chodzi o coś w stylu "if w if'e".
Offline
zrób while w którym sprawdzasz czy jest połączenie jak jest to wychodzisz z while, w srodku robisz sleep.
potem pod while robisz sprawdzenie poczty.
net=1 while [ ${net} -eq 1 ]; do if [ (jest net)]; then net=0 else sleep 10 fi done (sprawdz poczte)
Ostatnio edytowany przez djjanek (2015-08-08 08:06:23)
Offline
a po co niepotrzebna zmienna
while ! jest_net; do sleep 10; done sprawdz_poczte
Offline
Skrypt wygląda następująco:
#!/bin/bash WGET="/usr/bin/wget" login="login" #nickname pass="haslo" #password title=`curl -u $login:$pass --silent "https://mail.google.com/mail/feed/atom" | grep -oPm1 "(?<=<title>)[^<]+" | sed '1d'` numero="$(wget --secure-protocol=TLSv1 --timeout=3 -t 1 -q -O - \ https://${login}:${pass}@mail.google.com/mail/feed/atom \ --no-check-certificate | grep 'fullcount' \ | sed -e 's/.*<fullcount>//;s/<\/fullcount>.*//' 2>/dev/null)" $WGET -q --tries=20 --timeout=10 http://www.google.com -O /tmp/google.idx &> /dev/null function check { if [ -z "$numero" ]; then echo "Błąd sieci!" && notify-send --icon=$HOME/.icons/oxymoje/scalable/status/connect_no.png "Connect error!" "Brak połączenia z siecią lub inny błąd!" elif [ $numero = 0 ]; then echo "Gmail $numero" elif [ $numero = 1 ]; then echo "Gmail: 1" && notify-send --icon=$HOME/.icons/oxymoje/scalable/status/gmail.png "Masz $numero nową wiadomość:" "$title" elif [ $numero = 2 ] || [ $numero = 3 ] || [ $numero = 4 ]; then echo "Gmail: $numero" && notify-send --icon=$HOME/.icons/oxymoje/scalable/status/gmail.png "Nowa poczta" "Masz $numero nowe wiadomości" else echo "Gmail: $numero" && notify-send --icon=$HOME/.icons/oxymoje/scalable/status/gmail.png "Nowa poczta" "Masz $numero nowych wiadomości" fi } if [ ! -s /tmp/google.idx ]; then echo "net Offline.. czekam 10 sekund i sprawdzam ponownie..." sleep 10 else echo "net Online" check rm -rf /tmp/google.idx fi
pozostało jeszcze zastosować warunek sprawdzania łącza - pętlę: jeśli nie ma neta to niech pętla co 10 sekund sprawdza połaczenie z siecią aż do skutku, w kółko, aż bedzie połączenie z netem i wówczas niech wykonuje funkcję sprawdzania poczty (check).
nie moge tu zastosować pętli while ani until bo one przerywają skrypt a mi chodzi aby on pracował w kółko
Ostatnio edytowany przez macios4x (2015-08-08 20:54:50)
Offline
[quote=djjanek]można, a nawet trzeba by było
while [ true ]; do while ! jest_net; do sleep 10; done sprawdz_poczte done
[/quote]
Jak to zaimplementować do skryptu?
Offline
Zamiast dawać tyle elif-ów, mógłbyś dać instrukcję switch-case, trochę bardziej elegancko to wygląda. Jest też też komenda mktemp (albo mktmp?), która tworzy unikalny plik tymczasowy, przez co podwójne odpalenie skryptu nie powoduje problemów.
Offline
ps -eo pcpu,pmem,pid,cmd | sort -k 1 -r | grep -v %CPU
Z powyższego polecenia potrzebuję "wyciągnąć" kolumnę PID. Można je przepuścić przez potok | cut -d ' ' -f3 ale delimiter może być różny w zależności od ilości cyfr w PID i w wyniku nie ma wszystkich numerów PID. Jak je wylistować? Potrzebuję samą listę PID (bez spacji ani innych znaków) posortowaną od procesów najbardziej obciążających CPU
Ostatnio edytowany przez macios4x (2015-08-22 10:28:00)
Offline
awk? wtedy nawet grepa nie trzeba (na dobrą sprawę sorta też).
coś w stylu
awk '{print $3}'
na początek...
Offline
Mam mały skrypt (na razie roboczy) w którym chcę, by w przypadku wciśniecia klawisza ESCAPE natychmiast zakończyć skrypt ([b]ale bez wciskania ESCAPE i ENTER[/b]), ale w menu żeby można było wybierać na przykład 1 i zatwierdzić to ENTERem (każdy wybór menu zatwierdzać klawiszem ENTER oprócz wyjścia ESCAPE). Zrobiłem coś takiego ale to nie działa jak należy. Chodzi poprostu o to, aby wybór menu zatwierdzać ENTERem, a w przypadku wciśnięcia ESCAPE natychmiast zakończyć skrypt.
#!/bin/bash clear echo menu echo 1- jeden echo 2 - dwa echo ESC - wyjście read d case "$d" in "1") echo wybrales_jeden ;; "2") echo wybrales_dwa ;; *) echo wybrales_cos_innego esac read -s -n1 key case "$key" in $'\e') echo koniec exit;; esac
Problem byłby przede wszystkim jak menu bedzie rozbudowane do docelowo kilkunastu pozycji, chcąc wybrać na przykład 12.
PS. Jeśli nie można zastosować jednocześnie obydwu tych funkcji case, to może jakoś w taki sposób:
case "$key" in 1$'\e') echo koniec;;
tyle że zamiast przypisanego escape dać enter jeśli da radę?
Ostatnio edytowany przez macios4x (2015-08-27 09:52:02)
Offline
Sądząc po tym co widzę to - nie obrażając - nie dasz rady, bo w ogóle nie rozumiesz jak działają skrypty.
Napisałeś taki ładny kawałek kodu... i skąd Twój skrypt ma wiedzieć że wcisnąłeś escape? Przeanalizuj sobie działanie skryptu w momencie kiedy od razu po starcie wciskasz escape.
Na razie napisz uproszczoną wersję zakładając że wyboru dokonujesz jednym znakiem bez wciskania entera.
Offline
Małe nieporozumienie. Wiem że ten skrypt jest napisany wadliwie, ale chodziło mi o to, aby uwidocznić obydwie te funkcje case. Wracając do punktu wyjścia zacznijmy może od takiego skryptu:
#!/bin/bash clear echo menu echo 1- jeden echo 2 - dwa echo ESC - wyjście read -s -n1 key case "$key" in "1") echo wybrales_jeden ;; "2") echo wybrales_dwa ;; $'\e') echo koniec exit;; *) echo wybrales_cos_innego ;; esac
Tutaj skrypt działa poprawnie, o tym już wiedziałem wcześniej, ale sedno sprawy polega właśnie na tym, aby funkcje wyboru 1 i 2 (i w przyszłości dalsze - docelowo kilkanascie ich ma być) zatwierdzić ENTERem.
Offline
umieść read i case w pętli. przed pętlą zainicjalizuj jakąś zmienną pustym stringiem. w case w przypadku wciśnięcia prawidłowego klawisza po prostu zapisz go w tej zmiennej. po wciśnięciu enter sprawdź czy do zmiennej wpisana jest wartość i jeśli tak, wyskocz z pętli.
przed wejściem do pętli możesz zrobić
stty raw -echo
i odwróć działanie po wyjściu.
jak to zrobisz, pogadamy o wieloznakowych kombinacjach.
aha - i nie chodziło mi o to że skrypt jest błędny tylko czy rozumiesz gdzie jest błąd
Offline
#!/bin/bash clear echo menu echo 1- jeden echo 2 - dwa echo ESC - wyjście zm= stty raw -echo while true; do read -s -n1 key case "$key" in "1"$zm) echo wybrales_jeden;; "2"$'zm') echo wybrales_dwa;; $'\e') echo koniec exit;; *) echo wybrales_cos_innego ;; esac done
Coś w tym stylu? Gdzie jest błąd? Można jakoś bardziej "łopatologicznie" to objaśnić?
Offline
na razie zacznijmy od tego, że twój skrypt nie robi tego co napisałem tylko Coś Zupełnie Innego (TM).
prosto i łopatologicznie?
Offline
Skrypt ma się zachowywać inaczej w zależności czy wciśniesz esc lub coś innego. Więc musisz tą logikę innego zachowania w nim zawrzeć.
#!/bin/bash clear echo menu echo 1- jeden echo 2 - dwa echo ESC - wyjście potwierdz() { while true; do echo Potwierdz enterem read -s -n1 key if [ "$key" = '' ]; then echo Potwierdzone return 0 else echo Niepotwierdzone return 1 fi done } while true; do echo "Wybierz:" read -s -n1 key echo "wybrales:$key" case "$key" in "1") if potwierdz; then echo wybrales_jeden else continue fi ;; "2") if potwierdz; then echo wybrales_dwa else continue fi ;; $'\e') echo koniec exit;; *) echo wybrales_cos_innego ;; esac done
BTW. Sposób ethanka powinien być jeszcze prostszy, bez takiego śmiecenia w kodzie.
Ostatnio edytowany przez seler (2015-08-28 19:41:16)
Offline
Ja zaryzykuję stwierdzenie, że Bash jest troszkę zbyt skromny do większych zabaw, zawsze kiedyś będzie trzeba dodać pliczek konfiguracyjny, parsować XMLa, albo zapisać coś czy odczytać z bazy Sqlite, czy może pobrać jakieś dane z netu, i Bash nagle okaże się za krótki, do prawdziwej zabawy skryptologicznej polecam Pythona albo Perla.
Proponuję nie mieszać interpretera poleceń powłoki (nawet bardzo rozbudowanego), z językiem programowania, którym Bash nigdy nie był.
Pozdro
Offline
Działa dopóki w menu są [b]JEDNOcyfrowe[/b] opcje wyboru, ale nie działa jeżeli rozbuduje menu do kilkunastu pozycji...
Offline
czytać kolega umie?
pokaż działający kod z jednym znakiem, pogadamy o wieloznakowych.
żeby nie było że teoretyzuję: na codzień posługuję się bardzo podobnym programem (wpisywanie odczytów glukometru i ciśnieniomierza, tyle że nie mam podpiętego ekranu a tylko głośnik). a tam jest trochę więcej kombinacji (np. dwie czy trzy cyfry)...
Offline
Skrypt proponowany przez selera dział sprawnie dopóty, dopóki menu ogranicza się do 9 pozycji. Docelowo jednak chcę rozbudować go do parunastu pozycji.
read -s -n1 key
ogranicza wprowadzanie klawiszy do jednego, można to zmienić na -n2 ale wówczas trzeba by znać kod klawisza ENTER - tak jak Escape ma kod $'\e' to jaki kod ma ENTER? Jednak nawet wówczas, wprowdzając pozycję menu na przykład 10 to skrypt nie czekałby na poteierdzenie ENTERem.
Offline
czekaj, ty chcesz się nauczyć czy dostać gotowca? jeśli to drugie to po prostu napisz o co chodzi (np. że ci się nie chce, co moim zdaniem jest bardzo dobrym powodem, bo nie każdy jest zwolennikiem wynajdywania koła po raz kolejny) - dostaniesz gotowca.
jeśli chcesz siė nauczyć cofnij się do mojego posta (wiesz którego) i spróbuj to napisać. efekty umieść tutaj nawet jeśli nie działają.
chyba że (podobnie jak ja) chcesz się uczyć na przykładach - też napisz, bo dostaniesz wtedy fragment kodu z wyjaśnieniem.
to co, które rozwiązanie wybierasz?
btw. enter to albo \n albo \r (zawsze mi się miesza bo w różnych sytuacjacj jest inaczej).
Ostatnio edytowany przez ethanak (2015-08-30 13:28:55)
Offline
Wyjaśnijmy coś, nie każdy jest tak biegły w programowaniu. Zawsze łatwo mówić i myśleć że "skoro ja umiem i dla mnie to proste to dla innych też". Nic bardziej mylnego. Każdy ma swoje predyspozycje i mocne i słabe strony, jeden jest dobrym programistą a inny np sportowcem. Mi chodziło o to, aby krok po kroku, tak na chłopski rozum, przystępnymi słowami naświetlić i nakierować na właściwy tor, aby było jasne co konkretnie trzeba zrobić w danej sytuacji, a jeśli to nie pomoże i okaże się że nie daje rady z tym to trudno, to może wówczas "z gotowca" ściągne.
I jeszcze raz powtarzam, to że ktoś jest biegły w pewnej dziedzinie to nie znaczy że każdy inny też.
Offline
Sportowcem, powiadasz...
Ano, wyobraźmy sobie taką hipotetyczną sytuację, że młodemu człowiekowi trener usiłuje wytłumaczyć, że aby umieścić piłkę w bramce należy ją w kierunku owej bramki kopnąć prawą nogą. Młody człowiek najpierw pyta co to jest bramka, potem zamiast kopnąć prawą nogą rzuca piłke lewą ręką w kierunku do bramki prostopadłym, a na delikatne sugestie że może by wreszcie zrobił to o czym trener mówi - wyjaśnia wszem i wobec że jedni są dobrzy w sporcie, drudzy w programowaniu.
No, ale dość dygresji.
Jedną z podstawowch zasad programowania jest umiejętność doboru narzędzi (w tym podstawowego - języka programowania) do zadania. Jacekalex sugerował, że bash nie służy do tego, do czego chcesz go zastosować, ale jeśli koniecznie chcesz użyć czystego basha - proszę bardzo...
#!/bin/bash cyfry='[0-9]' maxv=12 echo -n "Wybierz pozycję od 1 do ${maxv}: " wybor='' function pasuje { [ -n "$1" ] && let "$1>=1" && let "$1<=${maxv}" } while true; do read -s -n1 znak if [ "${znak}" == "" ] ; then if pasuje ${wybor}; then break fi elif [[ "${znak}" =~ ${cyfry} ]] ; then tmp=${wybor}${znak} if pasuje $tmp; then wybor=${tmp} echo -n $znak fi elif [ "${znak}" == $'\e' ] ; then wybor='' break elif [ "${znak}" == $'\x7f' ] ; then if [ -n "${wybor}" ] ; then wybor=${wybor:0:-1} echo -ne '\b \b' fi fi done echo if [ -z "${wybor}" ] ; then echo "Jak nie to nie" exit 0 fi case "${wybor}" in 1|3|5|7|9) echo "Wybrałeś jednocyfrową liczbę nieparzystą: ${wybor}" ;; 2|4|6|8) echo "Wybrałeś jednocyfrową liczbę parzystą: ${wybor}" ;; *) echo "Wybrałeś dwucyfrowo: ${wybor}" ;; esac
Skrypt nawet działa - pod warunkiem, że nie będziesz naciskał innych klawiszy niż przykazane, szczególnie klawiszy funkcyjnych, kursorów i innego badziewia co sie pałęta na poboczu klawiatury. Dlaczego? A dlatego, że bash otrzymując dane z terminala nie jest w stanie stwierdzić, czy kod '\e' dostał w wyniku wciśnięcia klawisza esc, czy może jest to początek sekwencji identyfikującej klawisz funkcyjny (zresztą w ogóle nie jest to trywialne, na szczęście istnieją biblioteki - np. ncurses - które całą czarną robotę wykonują za nas). Zresztą - sam spróbuj, jak skrypt zareaguje np. na wciśnięcie "del" czy kursora...
Ale - wiedząc jak takowe sekwencje wyglądają, możemy nasz kod nieco poprawić:
elif [ "${znak}" == $'\e' ] ; then if ! read -t 1 -n 1 -s z; then wybor='' break else while [[ "$z" =~ ${cyfry} ]] || [ "$z" = '[' ]; do read -n 1 -s z done fi
Niestety - efektem ubocznym jest sekundowe opóźnienie reakcji na wciśnięcie esc. Co prawda niektóre wersje basha rozumieją timeout podany jako liczba z przecinkiem (0.1 sekundy jest w tym przypadku dość bezpieczną wartością) - ale nie wszystkie.
Można by też użyć polecenia sleep w wersji GNU - ale po pierwsze nie zawsze mamy dostęp do wersji GNU (a tylko ta rozumie czasy krótsze niż sekunda), po druge jest to jednak zewnętrzne polecenie (a miało to być zrobione w bashu).
Skrypt ma jeszcze jedną wadę - mianowicie nie odróżnia wciśnięcia enter od spacji. Po prostu - komenda read nie była projektowana do bezpośredniej komunikacji z klawiaturą i traktuje spację, tab i enter po prostu jako delimiter i w takim przypadku zwraca pusty string. Ale i na to jest rada - po prostu na czas wykonania read należy zmienić delimitery. Czyli kolejna poprawka:
while true; do IFS=$'\n' read -s -n1 znak
Jak widzisz - dało się zrobić ale po co się tak męczyć?
Tak przy okazji: dużo z tego kodu zrozumiałeś?
A, jeszcze mi się przypomniało:
"clear" jest co prawda dość bezpiecznym poleceniem, ale nie jest wewnętrznym poleceniem basha i - co najważniejsze - w wielu dystrybucjach domyślnie nie jest instalowany. Zamiast tego w miarę uniwersalnym poleceniem będzie:
echo -en '\x1b[H\x1b[2J'
Jako pracę domową (bo pierwszej nie odrobiłeś) napisz co ten tajemniczy napis oznacza ;)
Ostatnio edytowany przez ethanak (2015-08-31 08:53:49)
Offline
Time (s) | Query |
---|---|
0.00023 | SET CHARSET latin2 |
0.00006 | SET NAMES latin2 |
0.00095 | SELECT u.*, g.*, o.logged FROM punbb_users AS u INNER JOIN punbb_groups AS g ON u.group_id=g.g_id LEFT JOIN punbb_online AS o ON o.ident='3.133.117.107' WHERE u.id=1 |
0.00116 | REPLACE INTO punbb_online (user_id, ident, logged) VALUES(1, '3.133.117.107', 1732218921) |
0.00068 | SELECT * FROM punbb_online WHERE logged<1732218621 |
0.00100 | DELETE FROM punbb_online WHERE ident='3.141.38.5' |
0.00089 | SELECT t.subject, t.closed, t.num_replies, t.sticky, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, 0 FROM punbb_topics AS t INNER JOIN punbb_forums AS f ON f.id=t.forum_id LEFT JOIN punbb_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=3) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id=27604 AND t.moved_to IS NULL |
0.00015 | SELECT search_for, replace_with FROM punbb_censoring |
0.01100 | SELECT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM punbb_posts AS p INNER JOIN punbb_users AS u ON u.id=p.poster_id INNER JOIN punbb_groups AS g ON g.g_id=u.group_id LEFT JOIN punbb_online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0) WHERE p.topic_id=27604 ORDER BY p.id LIMIT 25,25 |
0.00356 | UPDATE punbb_topics SET num_views=num_views+1 WHERE id=27604 |
Total query time: 0.01968 s |