Jak zapętlić, czyli zaprojektować program do wykonywania powtarzalnej pracy za Ciebie
Pętla jest jedną z najbardziej podstawowych i potężnych konstrukcji w obliczeniach, ponieważ pozwala nam powtarzać zestaw poleceń tyle razy, ile chcemy, na liście wybranych przez nas elementów. Większość myślenia obliczeniowego wymaga podjęcia jednego zadania i rozwiązania go w sposób, który można zastosować wielokrotnie do wszystkich innych podobnych zadań, a pętla for to sposób, w jaki zmuszamy komputer do wykonywania tej powtarzalnej pracy:
W przeciwieństwie do większości kodu, który napisaliśmy do tej pory w interaktywnym znaku zachęty, pętla for nie jest wykonywana natychmiast po naciśnięciu Enter:
Możemy wypisać dowolną liczbę poleceń w bloku między słowami kluczowymi do
i done
:
Dopiero gdy osiągniemy done
i naciśniemy Enter, pętla for wykona swoją pracę.
To zasadniczo różni się od polecenia i odpowiedzi wiersz po wierszu, którego do tej pory doświadczyliśmy w zachęcie. I zapowiada, jak będziemy programować dalej: mniejszy nacisk na wykonywanie poleceń z każdej linii i większy nacisk na planowanie funkcjonalności programu, a następnie wykonanie go później.
Podstawowa składnia
Składnia for
pętli może być myląca, więc oto kilka podstawowych przykładów, które pomogą Ci je przygotować / odświeżyć:
Oto bardziej rozbudowana wersja wykorzystująca zmienne:
Do wygenerowania można użyć podstawienia polecenia elementy, w których pętla for
przechodzi iteracyjnie:
Jeśli chcesz przeczytać listę wierszy z pliku i są absolutnie pewni, że żadna z linii nie zawiera spacji:
Pętla do odczytu podczas jest odmianą powyższego, ale jest bezpieczniejsze do czytania wierszy z pliku:
Konstruowanie podstawowej pętli for
Zacznijmy od początku, bardzo minimalna for
pętla, a następnie wbudowana w coś bardziej skomplikowanego, aby pomóc nam zrozumieć ich cel.
Najprostsza pętla
To jest tak proste jak możesz zrobić pętlę for:
Czy wydawało się to całkiem bezwartościowe? Tak, powinno. Napisałem cztery wiersze kodu, aby zrobić to, co zajmuje jeden wiersz, echo "Hi"
.
Więcej elementów w kolekcji
To „Trudno powiedzieć, ale wykonano„ pętlę ”. Została wykonana tylko raz. OK, więc jak sprawić, by wykonywała się więcej niż jeden raz? Dodaj więcej (oddzielonych spacjami) elementów po prawej stronie elementu . Dodajmy jeszcze cztery 1
„s:
OK, niezbyt ekscytujące, ale program zdecydowanie wydawał się zapętlić: cztery 1
„s spowodowały wykonanie czterech echo
poleceń.
Co się stanie, gdy zastąpimy te cztery 1
„różnymi liczbami? I może kilka słów?
I… nic. Więc pętla nie robi automatycznie niczego specyficznego dla zbioru wartości, które jej podaliśmy. W każdym razie jeszcze nie.
Odnieś się do zmiennej pętli
Spójrzmy na lewo od słowa kluczowego in
i na to x
. Jaki jest sens tego x
? Mała litera x
nie jest „nazwą słowa kluczowego lub polecenia, które napotkaliśmy do tej pory (i wykonanie go samodzielnie po znaku zachęty spowoduje błąd). Więc może to jest zmienna? Spróbujmy odwołać się do niej w instrukcji echo
:
Bingo. To jest prawie podstawowe działanie pętli for
: – Pobierz zbiór elementów / wartości (Q Zebra 999 Smithsonian
) – Przekaż je do for
konstrukcja pętli – używając zmiennej pętli (x
) jako symbolu zastępczego, napisz polecenia między do
/ done
blok. – Podczas wykonywania pętli zmienna pętli x
przyjmuje wartość każdego elementu w lista – Q
, Zebra
, 999
, Smithsonian
, – i blok poleceń między do
i done
jest następnie wykonywany. Ta sekwencja powtarza się raz dla każdego elementu na liście.
Blok do
/ done
może zawierać dowolną sekwencję polecenia, nawet kolejne for
-loop:
Pętle w pętlach to typowa konstrukcja w programowaniu.W większości przypadków będę starał się unikać przypisywania problemów, które wymagałyby tego rodzaju logiki, ponieważ odkręcanie podczas debugowania może być trudne.
Czytaj plik wiersz po wierszu, niezawodnie z read-while
Ponieważ cat
drukuje plik wiersz po wierszu, następująca pętla for wydaje się sensowna:
Jednak podstawienie polecenia spowoduje, że cat
podzieli słowa spacjami. Jeśli list-of-dirs.txt
zawiera następujący:
Wynik pętli for
będzie wyglądał następująco:
Pętla do odczytu podczas, gdy zachowuje słowa w linii:
Możemy również potokować z wyniku polecenia, umieszczając je w <(
i )
:
Potoki i pętle
Jeśli pochodzisz z innych języków, strumienie danych mogą być dla Ciebie nieznane . Przynajmniej są dla mnie, ponieważ składnia do pracy z nimi jest o wiele bardziej bezpośrednia i prostsza w Bash niż w Ruby czy Pythonie.
Jednak jeśli jesteś nowy w programowaniu w jakimkolwiek języku, co może nie jest też jasne, czym różni się praca ze strumieniami danych od pracy z pętlami.
Na przykład następujący fragment:
– daje taki sam wynik jak ta pętla:
W zależności od twojego mentalnego modelu rzeczy wydaje się, że w obu przykładach każde słowo, np. hello
, world
, jest poddawany procesowi tłumaczenia (przez tr
), a następnie powtarzany.
Potoki i filtry
Bez wchodzenia w podstawy systemu uniksowego, w którym potok działa zasadniczo inaczej niż pętla, pozwól mi zasugerować mentalne obejście:
Programy, które przesyłają potok ze stdin i stdout, zwykle mogą być ułożone jako filtry, w których jest strumień danych przechodzi do programu i pojawia się w innym formacie:
W przypadku zadań, które są czymś więcej niż tylko przekształcaniem danych, od filtra do filtra, pomyśl o użyciu pętli. Jakie może być zadanie? Mając listę adresów URL, pobierz każdy z nich i wyślij e-mailem pobrane dane z dostosowaną treścią i tematem:
Źródło wprowadzania danych, każdy adres URL w urls.txt
, tak naprawdę nie jest tutaj filtrowane. Zamiast tego dla każdego adresu URL jest wykonywane wieloetapowe zadanie.
Przekierowanie do odczytu podczas odczytu
To powiedziawszy, można zaimplementować samą pętlę jako jeszcze jeden filtr wśród filtrów. Weź tę odmianę pętli read-while, w której wynik echo | grep
jest przesyłany potokiem, wiersz po wierszu, do while
pętla, która drukuje na standardowe wyjście za pomocą echo
, która jest przekierowywana do pliku o nazwie some.txt:
Nie jest to konstrukcja, którą być może będziesz musiał wykonywać często, jeśli w ogóle, ale miejmy nadzieję, że wzmacnia użycie potoku w Uniksie.
Mniej interaktywne programowanie
częste używanie pętli for
i podobnych konstrukcji oznacza, że „wychodzimy poza stare dobre” dni pisania w jednym wierszu litery c ommands i uruchamianie go zaraz po naciśnięciu Enter. Bez względu na to, ile poleceń spakujemy w pętli for
, nic się nie dzieje, dopóki nie trafimy na słowo kluczowe done
.
Napisz raz. Następnie zapętl to
Wraz z utratą interakcji linia po linii z powłoką, tracimy główną zaletę interaktywnej zachęty: natychmiastową informację zwrotną. Nadal mamy wszystkie wady: jeśli popełnimy literówkę wcześniej w bloku poleceń między do
a done
, musimy zacząć
Oto jak to złagodzić:
Testuj swój kod, pojedynczo
Jeden z największych błędów popełnianych przez nowicjuszy w for
uważają, że pętla for
natychmiast rozwiązuje ich problem. Jeśli więc muszą pobrać 10 000 adresów URL, nie mogą poprawnie pobrać tylko jednego adresu URL, uważają, że umieszczenie swoich błędnych poleceń w pętli for
jest krokiem we właściwym kierunku.
Poza tym jest to zasadniczo niezrozumienie pętli for
, praktyczny problem polega na tym, że teraz uruchamiasz uszkodzony kod 10 000 razy, co oznacza, że musisz czekać 10 000 razy dłużej, aby dowiedzieć się, że kod jest, niestety, nadal zepsuty.
Udawaj więc, że „nigdy nie słyszałeś o for
pętle. Udawaj, że musisz pobrać wszystkie 10000 adresów URL, jedno polecenie na raz. Czy możesz napisać polecenie, aby to zrobić dla pierwszego adresu URL. A co z drugim? Gdy masz już pewność, że żadne drobne błędy składniowe nie przeszkadzają Ci, czas pomyśleć o tym, jak znaleźć ogólny wzorzec dla 9 997 innych adresów URL.
Pisanie skryptów
Interaktywna linia poleceń jest świetna.Fajnie było zacząć i będzie fajnie przez całą twoją karierę komputerową. Ale kiedy masz przed sobą duże zadanie, obejmujące więcej niż dziesięć wierszy kodu, nadszedł czas, aby umieścić ten kod w Skrypt powłoki. Nie ufaj swoim omylnym ludzkim palcom, że bezbłędnie przepisują kod.
Użyj nano do pracy z pętlami i zapisz je jako powłokę skrypty. W przypadku dłuższych plików będę pracować w edytorze tekstu na komputerze (Sublime Text), a następnie przesyłam je na serwer.
Ćwiczenie ze skrobaniem sieci
Tylko po to, aby uziemić składnia i działanie pętli for, oto proces myślowy polegający na przekształceniu rutynowego zadania w pętlę:
Dla liczb od 1 do 10, użyj curl, aby pobrać wpis Wikipedii dla każdego numeru i zapisz go w pliku o nazwie „
wiki-number-(whatever the number is).html
”
Staromodny sposób
Mając zaledwie 10 adresów URL, mogliśmy ustawić kilka zmiennych, a następnie 10 razy skopiować i wkleić polecenie a curl, wprowadzając zmiany w każdym wierszu:
I wiecie co? To działa. W przypadku 10 adresów URL nie jest to złe rozwiązanie i jest znacznie szybsze niż robienie tego w staromodny sposób (robienie tego z poziomu przeglądarki internetowej)
Ograniczenie powtórzeń
Nawet nie myśląc o pętli, nadal możemy zmniejszyć liczbę powtórzeń, używając zmiennych: podstawowego adresu URL, i podstawowej nazwy pliku nigdy się nie zmieniają, więc przypiszmy te wartości zmiennym które można ponownie wykorzystać:
Stosowanie pętli for
W tym miejscu uprościliśmy wzorzec do tego stopnia, że możemy zobaczyć, jak małe zmiany w każdym oddzielnym zadaniu. Po zapoznaniu się z for
-loop, możemy go zastosować bez większego zastanowienia (dodajemy również polecenie uśpienia, abyśmy mogli robić przerwy między żądaniami sieciowymi)
Generowanie lista
W większości sytuacji utworzenie pętli for jest łatwe; to tworzenie listy może być ciężką pracą. A co by było, gdybyśmy chcieli zebrać strony dla numerów od 1 do 100? To dużo pisania.
Ale jeśli pozwolimy, by nasze lenistwo dyktowało naszym myśleniem możemy sobie wyobrazić, że liczenie od x do y wydaje się z natury zadaniem obliczeniowym. I tak jest, a Unix ma narzędzie seq
do tego:
Generowanie listy nieliczbowych do iteracji
Wiele powtarzalnych zadań czy nie są tak proste, jak liczenie od x do y, więc problem polega na tym, jak wygenerować nieliniową listę elementów? Na tym właśnie polega sztuka gromadzenia danych i zarządzania nimi. Ale stwórzmy prosty scenariusz dla sami:
W przypadku dziesięciu z 10-literowych (lub więcej) słów, które pojawiają się przynajmniej raz w nagłówku na bieżącej stronie głównej NYTimes.com, pobierz stronę Wikisłownika dla tego słowa
Dzielimy to zadanie na dwie części:
- Pobierz listę dziesięciu 10 + -litera słów z nagłówków nytimes.com
- Przekaż te słowa do naszej pętli for
Krok 1: Użycie narzędzia pup (lub parsera HTML wiersza poleceń Twój wybór):
Krok 2 (zakładając, że zmienna words
jest przekazywana dalej):
Sprawdź oprogramowanie re Carpentry’s doskonały przewodnik po pętlach for w Bash