Skocz do zawartości
atsiv

Bash, Sed - Howto

Rekomendowane odpowiedzi

Chciałbym napisać skrypt dla Debiana, który będzie aktualizować pobierać listę aktualizacji, instalować aktualizacje oraz instalować programy. Chciałbym aby to był bardziej zaawansowany skrypt, ponieważ taki prosty jestem wstanie napisać:

 

=====

#!/bin/bash

aptitude update

aptitude upgrade

aptitude install program0

aptitude install program1 program2

=====

 

Co prawda można mówić już o działającym skrypcie, ale na myśli mam bardziej zaawansowany, który będzie wypluwać komentarze. Np. jeśli "aptitude update" zadziała, tzn. że jest połączenie z internetem. Jeśli nie, to powinien wyskoczyć komunikat o braku połączenia z internetem. Jeśli "aptitude update" pobierze listę aktualizacji i nie wyskoczy jakiś błąd, powinien wyskoczyć komunikat potwierdzający powodzenie. Jeśli wyskoczę jakieś błędy, ponieważ repozytoria chwilowo nie działają lub w danym momencie padło połączenie z netem, powinien wyskoczyć komunikat, który poinformuje nas o napotkanym problemie.

 

Czy wie ktoś jak to zrobić lub mógłby podesłać jakiś przykładowy skrypt, który będzie pasować do mojego opisu?

Edytowane przez atsiv

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

Przecież aptitude [-v] wypluwa całą masę informacji do stdout - wystrczy to przefiltrować.

Sieć: nie widzę w tym większego sensu - chyba że skrypt ma sprawdzać czy połącznie zostało przywrócone i wówczas kontynuwać - wystarczy do tego śledzić f.e. syslog w oczekiwaniu na odpowiednie komunikaty NetworkManagera i avahi-daemona.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

OK ;) Jeszcze jedno pytanie. Gdy do instalacji niektorych pakietow uzywam Apt-get lup Aptitude wyskakuje pytanie czy napdpisac nowy plik konfiguracyjny na stary... Jest do wyboru tak, nie oraz domyslnie. Czy da sie zrobic tak, aby menedzer pakietow automatycznie odpowiadal na pytania bez udzialu usera, czyli sam wybieral opcje domyslnie?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

Wiesz, w przeciwieństwie do windy linux ma full dokumentację dostępną za free ;)

Tak więc po wpisaniu >man aptitude otrzymujemy cytuję:

"-y, --assume-yes

When a yes/no prompt would be presented, assume that the user entered “yes”. In particular, suppresses the prompt that

appears when installing, upgrading, or removing packages. Prompts for “dangerous” actions, such as removing essential

packages, will still be displayed. This option overrides -P.

" koniec cycatu :)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

O tym to akurat wiem (man nazwa_aplikacji) ;) Wytłumaczę może jeszcze raz co chciałem osiągnąć, ponieważ nie o to mi chodziło. Gdy aptitude pobierze paczki i zacznie je instalować czasami może wyskoczyć pytanie czy chcemy nadpisać lub zostawić stary plik konfiguracyjny. Jest do wyboru tak/nie/domyślnie. Czy da się zrobić, aby użytkownik zamiast odpowiadał na te pytanie, robiło sie automatycznie.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

przecierz -y właśnie do tego służy :blink:

Poza tym: wszystko zależy od innych opcji, jak remove/keep, safe-upgrade, itd. Opcja --assume-yes pozwala zaiplikować odpowiedź "yes" tylko dla zmian "niekrytycznych" czyli takich które nie grożą uszkodzeniu systemu - co chyba jest logiczne. Myślę że powinieneś dokładnie przeczytać manual...

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Fakt, masz rację. No cóż nie jestem najlepszy z angielskiego i zrozumiałem manuala do końca, ale dzięki. Mam pytanko ostatnie jeszcze. Załóżmy, że utworzyłem skrypt z 10 linijek i chciałbym, aby te 10 linijek powtórzył dwa razy, czy da się tak? wIEM, ŻE MOŻNA ZROBIĆ TAK: 10 + 10, ALE NIE BĘDZIE TO ZA ŁADNIE WYGLĄDAĆ ;)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

eee, to akurat jest proste ;)

np. wrzucasz apta w pętlę while lub for i jako argument podajesz mu linię z pliku zawierającego listę pakietów (i opcji).

plik odczytujesz linia po linii np. używając sed'a (język ufoludków, ale najszybszy ;) ), cat, awk itp.

 

edit: no i będzie okazja do zakumania regex'a :rolleyes:

Edytowane przez tomazzi

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Jeszcze jedno pytanie... Załóżmy, że ''cat plik'' wyświetla kilkadziesiąt zdań, które nie są zakończone żadnymi znakami interpunkcyjnymi. Chciałbym, aby skrypt pododawał te kropki na końcu zdań, czy wie ktoś jak to zrobić?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

hmm, no to będzie trudne - bo niby skąd program ma wiedzieć gdzie jest koniec zdania? - planujesz jakieś AI zastosować? ;)

Napisz konkretnie (przykład) co chcesz uzyskać.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

>echo qwertyuafdgfveoiurhv1234567890 | sed -n 's/./&./2 p'

>qw.ertyuafdgfveoiurhv1234567890

 

short info: "." (dot) - dowolny znak, & - ostanie "trafienie", 2-numer ostatniego "trafienia" (1-512)

 

na przyszłość:

znajomość regex (regular expressions) to podstawa w skryptach - bez tego nic nie zrobisz.

sed to potęga ;)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

O dzieki ;) No coz na razie ucze sie robic skrypty i zanim zaczne wiecej umiec minie jeszcze ;)

 

Jesli chpodzi o sed, racja, jest on straszna potega

 

Hmmm... a jeszcze jedno pytanie i byc moze na jakis czas ostenie ;) Zalozmy, ze cat pokazuje 8 wierszy wyrazow. chciabym, aby skrypt pomijal jeden wyraz, np. czerwony i pokazywal tylko 7... Pewnie tak tez da sie zrobic.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

:)

wycięcie tylko wyrazów "czerwony":

>cat colors.txt | sed 's/czerwony// p'

 

wycięcie linii zawierających wyraz "czerwony":

>cat colors.txt | sed '/czerwony/ d'

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

Pan sed może wszystko ;)

...można nim zastąpić 90% innych komend do edycji strumieni/tekstu (tail/head, cat, grep, context grep, awk, ... ). Jeśli chcesz pisać dobre skrypty to najlepiej nie używać 50-ciu "wygodnych" komend, za to lepiej użyć kilku wyciskając z nich wszystko co się da. Odbija się to bardzo pozytywnie na czasie startu skryptu i szybkości jego działania.

 

oprócz >man sed, polecam np. coś takiego: klik

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ja zanim załapie seda upłynie trochę wody w Wiśle. Mógłbyś podpowiedzieć jak zrobić za pomocą seda, aby zamiast liczył litery, dopiero wtedy stawiał kropkę na końcu pojedynczego wyrazu w wierszu oraz jak zrobić, aby w wierszu, w którym znajdują się dwa wyrazy pokazywał tylko pierwszy lub usuwał drugi?

Edytowane przez atsiv

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

najprostsze rozwiązania:

>echo "first second third" | sed -n 's/[^ ][^ ]*/&./1 p'

>first. second third

;1 - numer słowa po którym wstawiasz ".", podwójne spacje ignorowane (traktowane jako jedna)

;zamiast spacji można użyć także innego delimitera (rozdzielacza) wyrazów.

 

>echo "first second third" | sed -n '{s/[^ ][^ ]*/&\n/2;P}'

>first second

;2 - numer słowa na którym linia ma się skończyć

 

;)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Hmm... dzięki ;) pomalutku coraz jaśniejszy robi mi się ten sed ;)

 

problem polega jeszcze na tym, że nie do końca wiem po co są te [ ], [^ ], ukośniki itd., ale jak znajde czas to pewnie doczytam o tym jeszcze w google.

 

Przy wykorzystaniu awk końcowy wynik jest second:

echo "first second third" | awk '{print $2}'

Pewnie to samo można osiągnąć poprzez sed, tylko ciekawe jak ;)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

echo "first second third" | awk '{print $2}'

Pewnie to samo można osiągnąć poprzez sed, tylko ciekawe jak ;)

jeśli już to:

>cut -s -d" " -f2

Cut jest kilka razy lżejsze od awk i w tym przypadku awk to przerost formy nad treścią... ;)

 

sed:

>echo "first second third" | sed -n '{s_[^ ][^ ]*_\n&\n_2;s_^[^\n]*[ \n]__;P}'

>second

 

...wygląda kosmicznie - poza przypadkami extremalnymi (szybkość, nietypowe delimitery) łatwiej i czytelniej będzie zastosować do tego cut.

 

edit:

apropos []: definicja wzorca (pattern). Ostatni przykład z sed po polsku:

- znajdż ciąg składający się z jednej "nie-spacji" [^ ] i zero lub więcej "nie-spacji" [^ ]*

- do znalezionego ciągu dodaj na początku i na końcu newline \n&\n

- zamień ciąg rozpoczynający się na początku lini, składający się z dowolnej liczby "nie-końców-linii" ^[^\n]* i zakończony newline [\n] na "nic" - czyli usuń ten ciąg znaków

- wydrukuj pattern buffer do pierwszego znaku newline P.

:lol:

Edytowane przez tomazzi

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

Złe pytanie - nie czy, ale jak :)

a tak:

>cat /path/file | sed '$ d'

 

:rolleyes:

 

Weź się za tutorial który Ci wcześniej podałem...

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

To dość ciekawe zagadnienie - sed jest edytorem strumienia, więc nie wie kiedy nastąpi "koniec transmisji" danych.

Jednak, jak powiedziałem: sed może wszystko, tylko trzeba umieć się z nim dogadać w jego języku ;)

 

wersja lajtowa: znamy rozmiar pliku (ilość linii), f.e plik ma ich 10:

>cat /file | sed '8,$ d' - nie trzeba chyba komentować...

 

Schody zaczynają się gdy nie znamy ilości linii, a trzy ostatnie chcemy usunąć:

>cat /file | sed -n '{N;N;:nxtln;N;P;s_^[^\n]*\n__;b nxtln}'

 

... no ale jest mały trabol ;) - jak chcemy usunąć ostatnie 25 linii to wypadałoby użyć jakiejś cyferki:

>cat /file | sed -n '{:preload;N;s_[\n]_&_2;T preload;:nxtln;N;P;s_^[^\n]*\n__;b nxtln}'

... no i po sprawie - sed wywali 2+1 ostatnich linii

 

Spróbuj przetłymaczyć to na polski ;)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie żle ;) Już łatwiej do tego celu będzie użyć tail ;)

 

sed plik 'N;$!P;$!D;$d'

W ten sposób poleciały dwie ostatnie linijki :P

 

A tak na marginesie bo z tego co widzę wszystko oddziela się przecinkami z kropką. Co zrobić aby N;$!P;$!D;$d był traktowany jako całość, jedność? Załóżmy, że po $d zamierzam coś dodać jeszcze, ale już nie będzie pasowało do tamtego, tylko jako dalej.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

...oczywiście ;)

W Twoim przypadku i tak najwolniejszy będzie apt, więc nie ma co przesadzać. Samo tail rzadko jednak występuje samodzielnie w skrypcie - zazwyczaj wynik i tak ląduje w grep, awk, sed - co skutkuje odpaleniem dodatkowych subprocesów - w mgnieniu oka może zjeść kilka MB ram + psuje context cache CPU. Sed to jeden malutki proces i w tym tkwi jego siła ;)

...btw: wiesz chyba, że w powyższych przykładach >cat jest również zbyteczne? ;)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gość <account_deleted>

sed plik 'N;$!P;$!D;$d'

W ten sposób poleciały dwie ostatnie linijki :P

 

A tak na marginesie bo z tego co widzę wszystko oddziela się przecinkami z kropką. Co zrobić aby N;$!P;$!D;$d był traktowany jako całość, jedność? Załóżmy, że po $d zamierzam coś dodać jeszcze, ale już nie będzie pasowało do tamtego, tylko jako dalej.

...trochę się mineliśmy z postami... ;)

Dobra, ale nie do końca kumam ocb...

O ile dobrze Cię rozumiem: chodzi o to że "d" powoduje restart skryptu sed'a? ...a chciałbyś napisać jakiś większy programik?

... do tego służy grupowanie komend w {} - "d" przechodzi wówczas do następnej grupy a nie na początek skryptu ;)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Tzn. zaciekawił mnie ten sed i po prostu się nim bawię ;) Można uznać, że tworzę większy program, ale dla siebie i dla zabawy ;)

 

Tak ja pisałem wcześniej N;$!P;$!D;$d kasuje dwie ostatnie linijki.

 

Teraz próbuje to uname -s zintegrować z tamtym, aby oprocz kasowania dwoch linijek, kasował jeszcze to co pokaze wynik uname -s ;)

 

Póki co nie wychodzi mi...

Edytowane przez atsiv

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie



×
×
  • Dodaj nową pozycję...