W sobie Poprzedni artykuł Opowiedziałem wam na podstawowym poziomie, jak działa każdy z najczęściej używanych znaków specjalnych w wyrażeniach regularnych. Dzięki tym wyrażeniom regularnym można przeprowadzać złożone wyszukiwania w plikach tekstowych lub w wynikach innych poleceń. W tym artykule wyjaśnię, jak używać polecenia sed do znajdowania i zastępowania tekstu w znacznie skuteczniejszy sposób niż po prostu zmienianie jednego tekstu na inny.
Trochę więcej o poleceniu grep
Zanim zacznę mówić o sedzie, chciałbym nieco bardziej skomentować polecenie grep, aby dokończyć to, co zostało wyjaśnione w poprzednim artykule. Wszystko, co powiem, będzie dotyczyło również tego. Później zobaczymy związek między tym a wyszukiwaniami.
Łączenie wyrażeń regularnych
Wiele znaków specjalnych, o których mówiłem w poprzednim artykule, można łączyć nie tylko z innymi znakami, ale z całymi wyrażeniami regularnymi. Aby to zrobić, użyj nawiasów do utworzenia podwyrażenia. Zobaczmy przykład tego. Zacznijmy od pobrania tekstu, którego możemy użyć do testów. To jest lista fraz. W tym celu użyjemy następującego polecenia:
curl http://artigoo.com/lista-de-frases-comparativas-comicas 2>/dev/null | sed -n 's/.*\(.*\.\)<\/p>/\1/gp' > frases
Spowoduje to pozostawienie Cię w katalogu, w którym uruchomisz plik o nazwie «frazy». Możesz go otworzyć, aby spojrzeć i trochę się pośmiać. 🙂
Załóżmy teraz, że chcemy znaleźć frazy, które mają dokładnie 6 słów. Trudność polega na utworzeniu wyrażenia regularnego pasującego do każdego słowa. Słowo to sekwencja liter, wielkich lub małych, które wyglądałyby podobnie '[a-zA-Z]+'
ale musisz też określić, że te litery muszą być oddzielone innymi znakami niż litery, to znaczy, byłoby to coś w rodzaju '[a-zA-Z]+[^a-zA-Z]+'
. Pamiętajmy: „^” jako pierwszy znak w nawiasach oznacza, że chcemy dopasować do znaków spoza zakresów, a „+” oznacza 1 lub więcej znaków.
Mamy już wyrażenie regularne, które może dopasować słowo. Aby sparować go z 6, trzeba będzie powtórzyć 6 razy. W tym celu użyliśmy kluczy, ale nie ma to sensu '[a-zA-Z]+[^a-zA-Z]+{6}'
, ponieważ 6 powtórzyłoby ostatnią część wyrażenia regularnego, a chcemy powtórzyć to wszystko, więc musisz wpisać to: '([a-zA-Z]+[^a-zA-Z]+){6}'
. Używając nawiasów, tworzymy podwyrażenie, a nawiasami powtarzamy je 6 razy. Teraz wystarczy dodać „^” z przodu i „$” z tyłu, aby dopasować całą linię. Polecenie jest następujące:
grep -E '^([a-zA-Z]+[^a-zA-Z]+){6}$' frases
Wynik jest dokładnie taki, jakiego chcieliśmy:
Jest bardziej śpiewana niż Macarena. Jesteś bardziej skończony niż Luis Aguilé. Masz mniej kultury niż kamień. Znasz więcej języków niż Cañita Brava. Ma więcej zmarszczek niż Tutan Khamón. Wiesz mniej niż Rambo o opiece nad dziećmi.
Zauważ, że wstawiliśmy parametr -E, ponieważ chcemy użyć rozszerzonych wyrażeń regularnych, aby „+” działało. Gdybyśmy użyli podstawowych, musielibyśmy uniknąć nawiasów i nawiasów klamrowych.
Odniesienia wsteczne lub odwołania wsteczne
Jeśli masz zainstalowany moduł sprawdzania pisowni, prawdopodobnie będziesz mieć listę słów w /usr/share/dict/words
. Jeśli nie, możesz zainstalować go w łuku za pomocą:
sudo pacman -S words
Lub w Debianie z:
sudo aptitude install dictionaries-common
Jeśli chcesz, możesz przejrzeć plik, aby zobaczyć, jakie słowa zawiera. Właściwie jest to link do pliku słów języka, w którym znajduje się twoja dystrybucja. Możesz mieć jednocześnie zainstalowanych kilka plików tekstowych.
Będziemy używać tego pliku. Okazuje się, że jesteśmy bardzo ciekawi wszystkich siedmioliterowych palindromów. Dla tych, którzy nie wiedzą: palindrom to słowo capicúa, to znaczy można je czytać od lewej do prawej oraz od prawej do lewej. Wypróbujmy następujące polecenie:
grep '^\(.\)\(.\)\(.\).\3\2\1$' /usr/share/dict/words
Wygląda to trochę dziwnie, prawda? Jeśli spróbujemy, wynik będzie zależał od języka twojej dystrybucji i słów z twojej listy, ale w moim przypadku, w przypadku języka hiszpańskiego, wynik będzie taki:
anilina walcowanie aniliny
Zobaczmy, jak działa to wyrażenie regularne.
Oprócz „^” i „$”, do których już wiemy, do czego służy, pierwszą rzeczą, którą widzimy po lewej stronie, są trzy grupy kropek ujęte w nawiasach. Nie daj się zmylić słupkami przed każdym nawiasem. Mają unikać nawiasów, ponieważ używamy podstawowych wyrażeń regularnych, ale nie mają one innego znaczenia. Ważne jest to, że prosimy o dowolne trzy znaki z kropkami, ale każda z tych kropek jest ujęta w nawias. Ma to na celu zapisanie znaków pasujących do tych punktów, aby można było ponownie odwołać się do nich z wyrażenia regularnego. Jest to kolejne użycie nawiasów, które przydadzą się później przy zastępowaniu.
Tutaj znajdują się trzy poniższe liczby z ukośnikiem przed nimi. W tym przypadku pasek jest ważny. Służy do wskazania, że poniższa liczba jest odwołaniem wstecznym i odnosi się do jednego z poprzednich nawiasów. Na przykład: \ 1 odnosi się do pierwszego nawiasu, \ 2 do drugiego i tak dalej.
Oznacza to, że w przypadku wyrażenia regularnego, które wstawiliśmy, szukamy wszystkich słów, które zaczynają się od dowolnych czterech liter, a następnie mają jedną taką samą jak trzecią, inną, która jest taka sama jak druga i kolejną, która jest taka sama jak pierwszy. Rezultatem są siedmioliterowe palindromy, które znajdują się na liście słów. Tak jak chcieliśmy.
Gdybyśmy używali rozszerzonych wyrażeń regularnych, nawiasy nie musiałyby zostać zmienione, ale w przypadku rozszerzonych wyrażeń regularnych odwołania wsteczne nie działają we wszystkich programach, ponieważ nie są ustandaryzowane. Jednak z grep działają, więc może to być inny sposób na zrobienie tego samego. Możesz spróbować, jeśli chcesz.
Wyrażenia zastępcze: polecenie sed
Oprócz wyszukiwania jednym z najlepszych zastosowań wyrażeń regularnych jest zastępowanie złożonych tekstów. Aby to zrobić, jednym ze sposobów jest użycie polecenia sed. Siła polecenia sed wykracza daleko poza zastępowanie tekstu, ale tutaj zamierzam go do tego użyć. Składnia, której będę używać z tym poleceniem, jest następująca:
sed [-r] 's/REGEX/REPL/g' FICHERO
Lub też:
COMANDO | sed [-r] 's/REGEX/REPL/g'
Gdzie REGEX będzie wyrażeniem regularnym wyszukiwania, a REPL będzie zastępczym. Pamiętaj, że to polecenie tak naprawdę nie zastępuje niczego w wskazanym przez nas pliku, ale pokazuje nam wynik zamiany w terminalu, więc nie bój się poleceń, które zamierzam wstawić dalej. Żaden z nich nie będzie modyfikował żadnych plików w twoim systemie.
Zacznijmy od prostego przykładu. Wszyscy mamy różne pliki konfiguracyjne w katalogu / etc, które zwykle mają komentarze zaczynające się od „#”. Załóżmy, że chcemy zobaczyć jeden z tych plików bez komentarzy. Na przykład zamierzam to zrobić za pomocą pliku fstab. Możesz spróbować z tym, który chcesz.
sed 's/#.*//g' /etc/fstab
Nie zamierzam tutaj umieszczać wyniku polecenia, ponieważ zależy to od tego, co masz w swoim fstab, ale jeśli porównasz wynik polecenia z zawartością pliku, zobaczysz, że wszystkie komentarze zniknęły.
W tym poleceniu wyrażeniem wyszukiwania jest «#.*
", To jest" # ", po którym następuje dowolna liczba znaków, czyli komentarze. A wyrażenie zastępcze, jeśli spojrzysz na dwa słupki z rzędu, zobaczysz, że ich nie ma, więc to, co robi, polega na zastępowaniu komentarzy niczym, czyli ich usuwaniu. Prostsze niemożliwe.
Teraz zrobimy odwrotnie. Załóżmy, że chcemy skomentować wszystkie wiersze pliku. Spróbujmy tak:
sed 's/^/# /g' /etc/fstab
Zobaczysz, że w danych wyjściowych polecenia wszystkie wiersze zaczynają się od znaku krzyżyka i spacji. To, co zrobiliśmy, to zastąpienie początku wiersza słowem «#
«. Jest to również dość prosty przykład, w którym tekst do zastąpienia jest zawsze taki sam, ale teraz będziemy to nieco bardziej skomplikować.
Łaska zamiany polega na tym, że w wyrażeniu zastępującym można używać odwołań wstecznych, takich jak te, o których mówiłem wcześniej. Wróćmy do pliku fraz, który pobraliśmy na początku artykułu. Zamierzamy umieścić w nawiasach wszystkie dostępne duże litery, ale zrobimy to za pomocą polecenia:
sed 's/\([A-Z]\)/(\1)/g' frases
Mamy tutaj odniesienie wsteczne w wyrażeniu zastępującym, które odnosi się do nawiasów w wyrażeniu wyszukiwania. Nawiasy w wyrażeniu zastępującym są zwykłymi nawiasami. W wyrażeniu zastępczym nie mają one specjalnego znaczenia, są umieszczone tak, jak są. W rezultacie wszystkie wielkie litery są zastępowane przez tę samą literę, cokolwiek to jest, z nawiasami wokół niej.
Istnieje inny znak, którego można również użyć w wyrażeniu zastępującym, jest to „&” i jest on zastępowany przez cały tekst dopasowany przez wyrażenie wyszukiwania. Przykładem może być umieszczenie wszystkich fraz w pliku w cudzysłowie. Można to osiągnąć za pomocą tego polecenia:
sed 's/.*/"&"/g' frases
Działanie tego polecenia jest bardzo podobne do poprzedniego, tylko że teraz zastępujemy cały wiersz tym samym wierszem z cudzysłowami. Ponieważ używamy „&”, nie musimy umieszczać nawiasów.
Kilka przydatnych poleceń z wyrażeniami regularnymi
Oto kilka poleceń, które uważam za przydatne lub ciekawe i używają wyrażeń regularnych. Dzięki tym poleceniom użyteczność wyrażeń regularnych jest znacznie lepsza niż w przypadku przykładów, które przedstawiłem do tej pory, ale wydawało się ważne, aby wyjaśnić coś o działaniu wyrażeń regularnych, aby je zrozumieć.
- Pokaż sekcje strony podręcznika:
man bash | grep '^[A-Z][A-Z ]*$'
Oczywiście możesz zmienić polecenie bash na cokolwiek chcesz. A potem od człowieka możesz przejść bezpośrednio do interesującej Cię sekcji, używając oczywiście wyrażenia regularnego. Naciskasz «/», aby rozpocząć wyszukiwanie i pisać «^ALIASES$
»Na przykład, aby przejść do sekcji ALIASY. Myślę, że jest to pierwsze użycie wyrażeń regularnych, które zacząłem kilka lat temu. Poruszanie się po niektórych stronach podręcznika jest prawie niemożliwe bez takiej sztuczki.
- Pokaż nazwy wszystkich użytkowników maszyny, w tym specjalnych:
sed 's/\([^:]*\).*/\1/' /etc/passwd
- Pokaż nazwy użytkowników, ale tylko te z powłoką:
grep -vE '(/false|/nologin)$' /etc/passwd | sed 's/\([^:]*\).*/\1/g'
Naprawdę można to zrobić za pomocą jednego wyrażenia regularnego, ale sposób wykonania tego wykracza poza to, co powiedziałem w tych artykułach, więc zrobiłem to, łącząc dwa polecenia.
- Wstaw przecinek przed trzema ostatnimi cyframi wszystkich liczb w pliku liczb:
sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers
Działa tylko z liczbami do 6 cyfr, ale można go wywołać więcej niż jeden raz, aby umieścić separatory w innych grupach trzech cyfr.
- Wyodrębnij wszystkie adresy e-mail z pliku:
grep -E '\<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}\>' FICHERO
- Oddziel dzień, miesiąc i rok wszystkich dat pojawiających się w pliku:
sed -r 's/([0-9]{2})[/-]([0-9]{2})[/-]([0-9]{4})/Día: \1, Mes: \2, Año: \3/g' FICHERO
- Sprawdź nasz lokalny adres IP:
/sbin/ifconfig | grep 'inet .*broadcast' | sed -r 's/[^0-9]*(([0-9]+\.){3}[0-9]+).*/\1/g'
Można to również zrobić pojedynczym poleceniem seda, ale dla uproszczenia lepiej rozdzielę je na grep i sed.
Kilka przydatnych adresów
Oto kilka adresów, które mogą być przydatne w przypadku wyrażeń regularnych:
- Biblioteka wyrażeń regularnych: To jest biblioteka wyrażeń regularnych, w której możesz wyszukiwać wyrażenia regularne związane z tematem, który Cię interesuje. Aby wyszukać adresy internetowe, identyfikator lub cokolwiek innego.
- RegExr: Narzędzie do sprawdzania wyrażeń regularnych online. Pozwala na wprowadzenie tekstu i zastosowanie do niego wyrażenia regularnego albo wyszukaj, albo zamień. Zawiera informacje o wyrażeniu regularnym i masz kilka opcji zmiany jego zachowania.
- Tester wyrażeń regularnych: Jest to dodatek do przeglądarki Firefox, który umożliwia sprawdzanie wyrażeń regularnych w przeglądarce.
Wnioski
Na razie to wszystko. Wyrażenia regularne są złożone, ale przydatne. Potrzeba czasu, aby się ich nauczyć, ale jeśli jesteś podobny do mnie, zabawa z nimi będzie wydawać się zabawna i stopniowo opanujesz je. To cały świat. Byłoby jeszcze wiele do powiedzenia na temat leniwych kwantyfikatorów, wyrażeń regularnych w stylu PERL, multilinii itp. A potem każdy program ma swoje cechy i warianty, więc najlepszą radą, jaką mogę ci dać, jest zawsze przeglądanie dokumentacji programu, którego używasz, za każdym razem, gdy musisz napisać wyrażenie regularne w nowym programie.
Hej! …HEJ! … OBUDŹ SIĘ! … CO WSZYSCY ŚPIĄCIE? 🙂
Fuentes
Niektóre pomysły i przykłady wyrażeń regularnych w tym artykule zaczerpnąłem stąd:
- http://sed.sourceforge.net/sed1line.txt
- http://www.thegeekstuff.com/2009/10/unix-sed-tutorial-advanced-sed-substitution-examples/
Mistrzowski!!!
Nie jest tak źle, ale bardzo dziękuję. Mam nadzieję, że ludzie to lubią. 🙂
Podoba mi się ha!
Więc musiałem zrobić coś dobrze. LOL!! 🙂
Bardzo dziękuję za komentarz.
Kurwa, pisz dalej stary, tak trzymaj.
@Blaire Pascal: Komentarze takie jak Twoje zachęcają do tego. 🙂 Dziękuję bardzo !!
Też mi się podobało ... dzięki 🙂
Dziękuję za komentarz. Mam nadzieję napisać jeszcze kilka. 🙂
Twoje posty są fantastyczne, dużo się uczysz, raczej uczysz się wykonywać zadania w elegancki i efektywny sposób.
Czy myślałeś o zebraniu wszystkich swoich postów w skryptach powłoki? Posortowany w formacie PDF byłby świetnym podręcznikiem.
Pozdrawiam i bardzo dziękuję!
Wielkie dzięki!! To niezły pomysł. Na razie są tylko dwa, ale o tym pomyślę później. 🙂
bardzo dobry artykuł, 5+.
Dziękuję Ci. Cieszę się że ci się podoba. 🙂
Świetny! Muszę zmienić następujące wyrażenie i nie wiem, jak to zrobić:
192.168.0.138/Server przez 192.168.0.111/data
Problem tkwi w symbolu „/”.
Używam polecenia:
odnaleźć. -name "* .txt" -exec sed -i 's / TEKST1 / TEKST2 / g' {} \;
Czego używa się do wykonywania tego typu zadań lekkomyślnie, ale nie mogę ...
Czy ktoś wie, jak mam to zrobić?
Uścisk!
Seba
Musisz uciec od postaci w ten sposób:
odnaleźć. -name "* .txt" -exec sed -i 's / \ / Server / \ / data / g' {} \;
Możesz także użyć innego separatora w sedzie. To nie musi być bar. Sed pozwala na użycie dowolnej postaci. Na przykład byłoby to jaśniejsze:
odnaleźć. -name "* .txt" -exec sed -i | / Server | / data | g '{} \;
A jeśli zamierzasz skopiować i wkleić polecenia z tego komentarza, uważaj na cudzysłowy, ponieważ wordpress zmienia je na typograficzne. 🙂
Pozdrowienia.
Doskonałe !!!!
Długo szukałem tego rozwiązania.
Tutaj zostawiam całe polecenie, którego użyłem
odnaleźć. -name "* .txt" -exec sed -i 's | 192 \ .168 \ .0 \ .238 \ / Server | 192 \ .168 \ .0 \ .111 \ / data | g' {} \;
Zaletą tego polecenia jest to, że rekurencyjnie zmienia wszystkie pliki .txt (lub żądane rozszerzenie) ... Musisz być bardzo ostrożny!
Ale to jest bardzo przydatne !!!
Cóż, dziękuję za wszystko i gratulacje dla całej grupy.
Zawsze czytam je z poczty!
Uściski
Seba