Articles

Przykłady Bash Sed

Bash pozwala na wykonanie zamiany wzorców używając ekspansji zmiennych jak (${var/pattern/replacement}). I tak samo robi sed (sed -e 's/pattern/replacement/'). Jednakże, jest coś więcej w sed niż zastępowanie wzorców w plikach tekstowych. Tutaj odkryjemy sed na nowo, na przykładach, z równoważnymi komendami i przepływami pracy, aby pomóc w codziennych zadaniach.

Ustawienia dla przykładów sed

Oto szybki przewodnik, jak ustawić się do przykładu, którego postaram się nie robić zbyt przekombinowanym.

„słowa” to plik tekstowy zawierający liczby od 1 do 100. Jeśli nie jesteś pewien, jakie polecenie go utworzyć, zobacz Funkcja eksportu dla xargs w poleceniu eksportu Bash. Nigdy nie wiesz, że może się to znaleźć na twojej następnej rozmowie o skryptach powłoki.

„bar” jest plikiem tekstowym zawierającym pojedynczą linię -.

„old-php” jest plikiem tekstowym zawierającym linie starego PHP, które zostaną złamane w php7 lub później. (Podpowiedź: ereg)

Zauważ, że wszystkie funkcje opisane powyżej można znaleźć poniżej w Endnote na temat funkcji dla setup.

Przykłady z równoważnymi komendami

W środowisku wiersza poleceń, znajdziesz więcej niż jedno rozwiązanie danego zadania. Jednakże, w większości przypadków, chcesz iść ścieżką, która przynosi najmniejszy opór. Oto lista przykładowych komend sed z odpowiadającymi im równoważnymi komendami, gdzie niektóre z nich zostaną szczegółowo omówione poniżej.

1. Wypisz losową linię (odpowiednik sort -R – | head -1)

sed -n „$(( RANDOM % 100 ))p” –

2.Wydrukuj ostatnią linię w pliku (odpowiednik head -1 -)

sed -n '$p' –

3. Wydruk pierwszych 10 linii w pliku (odpowiednik head -n 10 -)

sed ’10q' –

4. Wypisanie pierwszej linii w pliku (odpowiednik tail -1 -)

sed -n '1p' –

5. Usunięcie wszystkich wystąpień znaku (odpowiednik tr -delete '0′ -, gdzie 0 jest znakiem, który chcemy usunąć)

sed -e 's/0//g' –

6. Konwersja pliku csv do tsv (odpowiednik tr ',' '\t' -)

sed -e 's/,//g' –

7.Dołączanie linii do pliku (odpowiednik cat bar -)

sed '$a —' –

8. Dołączanie linii do pliku (odpowiednik cat – bar)

sed '1i —' –

9. Wypisanie wszystkich linii w pliku (odpowiednik cat -)

sed -n -e 'p' –

10. Wypisanie linii pasujących do wzorca (odpowiednik grep -e '^1′ -)

sed -n -e '/^1/ p' –

11. Usuwanie linii pasujących do wzorca (odpowiednik grep -v -e '^1′ -)

sed -e '/^1/ d' –

12. Uzyskaj liczbę linii w pliku (odpowiednik wc -l -)

sed -n -e '$=' –

13. Zapisywanie do pliku w tle(odpowiednik polecenia tee)

sed „w ${1}” –

Przykład użycia sed do implementacji polecenia tee

Prawie powyżej, znajduje się przykład oznaczony jako Write to a file in the background. Brzmi to trochę jak polecenie tee. Cóż, tak właśnie jest. Tutaj dowiemy się, jak zaimplementować funkcję zastępującą tee w bashu za pomocą sed.

Komendy

tee ()
{
test ${#} -eq 1 || return;
sed „w ${1}” –
}
main ()
{
seq 10 | tee ten;
cat ten
}
main

Output

1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10

W tym miejscu zobaczysz dwie listy liczb całkowitych od 1 do 10. Pierwszy z nich pochodzi z polecenia seq. Drugi dostajemy z cat pliku napisanego w tee. Wiem, że to niedorzeczne, ale działa!

Przykład użycia sed do wypisania losowej linii w pliku

Załóżmy, że chcemy wypisać losową linię w pliku używając basha i odrobiny sed. Czy możemy to zrobić? Tak, możemy! Oto jak.

Zaimplementuj funkcję, która

  1. Pobiera liczbę linii w pliku, L
  2. Generuje liczbę losową pomiędzy 1 a L, R
  3. Wypisuje R

Funkcja oczekuje, że dane wejściowe zostaną przesłane z zewnątrz.

Komendy

some-line ()
{
function lc ()
{
sed -n -e '$=' –
};
function print-line ()
{
sed -n -e „${1}p” –
};
temp=$( mktemp );
cat – > ${temp};
cat ${temp} | print-line $(( RANDOM % $( cat ${temp} | lc ) + 1 ));
rm ${temp}
}

Przykładowe użycie (1)

seq 100 | _

Wyjście (1)

35

Przykładowe użycie (2)

curl https://linuxhint.com/bash_cut_command/ -.-silent | strip-tags | some-line

Zobacz poniższy przykład, używający sed do usuwania znaczników HTML. Zauważ, że powyższy przykład czasami zwraca puste linie. Jako ćwiczenie, można to poprawić.

Użycie sed do wypisania linii w pliku

Załóżmy, że chcesz zaimplementować w bashu funkcję do wypisania danej linii w pliku. Próba wydrukowania pojedynczej linii w pliku przy użyciu pętli w bashu, head, tail lub awk jest zbyt pracochłonna jak na drukowanie linii w pliku. Dobrze, że mamy sed. Funkcja wynikowa przy użyciu sed wyglądałaby następująco.

Komendy

print-line ()
{
sed -n „${1}p” –
}

Zobaczmy teraz, co się stanie, gdy użyjemy print-line na słowach.

Komendy

słowa | print-line 50

Wyjście

50

Dobrze. Wygląda dobrze, ale spróbujmy czegoś, co wygląda nieco mniej trywialnie.

Komendy

declare -xf words
declare -xf print-line
seq 1 10 $( words | wc -l )| xargs -i bash -c „words | print-line {}”

Output

1
11
21
31
41
51
61
71
81
91

Dobra. Teraz to jest bardziej jak to! Widzisz jak sed może być użyty w skrypcie basha do wypisania dowolnej linii w pliku.

Przykłady sed bez równoważnych poleceń

W środowisku wiersza poleceń, czasami droga do rozwiązania przynoszącego najmniejszy opór jest drogą sed; w przeciwnym razie, kończysz wykonując więcej pracy niż jest to wymagane na pierwszym miejscu. Niektóre komendy mogą być przedstawione poniżej.

Komenda wszystkich wierszy w skrypcie powłoki

sed -e 's/^/#/' –
Usuń pierwszy wiersz
sed -e '1d' –
Usuń ostatni wiersz
sed -e '$ d' –
Usuń ostatni wiersz
sed -e '$ d'
Wstawia linię przed liniami pasującymi do wzorca
sed '/0$/i —' –
Wstawia linię po liniach pasujących do wzorca
sed '/0$/ —' –
Usuwa znaczniki html
sed -e 's/<*.//g' –
Uaktualnij ereg w starym kodzie php, aby działał w php7 lub nowszym
sed 's/ereg(\\.\\./strpos(\2,\1)/g'
Sprawdź, czy sed jest wcześniejszy niż określona wersja
sed -e 'v 4.5′ –

Przykładowe rozgałęzianie wersji sed w bashu

Powyżej w przykładach znajduje się linia do Sprawdzania, czy sed jest wcześniejszy niż określona wersja, którą możemy wykorzystać do implementacji rozgałęziania wersji w bashu, co moim zdaniem jest łatwiejsze niż próba implementacji funkcji do porównywania numerów wersji z wyjścia sed -version. Jedyną pułapką jest to, że jeśli istnieje wcześniejsza wersja sed, która nie obsługuje komendy v, wtedy mamy kłopoty.

Rozporządzenia

test-sed-version-at-most() {
echo -.n | sed „v ${1}” – 2>/dev/null
}
try-version ()
{
echo -n „Wersja ${1}. Ok. Zrób to „;
test-sed-version-at-most ${1}. && {
echo -n „old”;
true
} || {
echo -n „new”
};
echo ” way.”
}
main ()
{
local v;
for v in 4.{4,5};
do
try-version ${v};
done
}
main

Output

Wersja 4.4. Okay. Zrób to po staremu.
Wersja 4.5. Okay. Zrób to w nowy sposób.

Zauważ, że wersja sed działająca na moim komputerze w momencie wpisywania tych znaków to 4.4, co wyjaśniałoby powyższe dane wyjściowe. Ponadto, w tym samym czasie, najnowsza wersja gnu sed była 4.7, około 3 lata starsza niż ta, którą mam. Mój sed jest stary! W rzeczywistości, w sed 4.0.6, parametr został dodany do polecenia wersji, więc ta strategia działa dla każdego, co najmniej v4.0.6, co jest pobłażliwe, biorąc pod uwagę, że ta wersja została wydana na początku 2003 roku. Jesteś dobry.

Zrobiłem trochę dodatkowego kopania, właściwie NEWS czytając z najnowszego kodu źródłowego. Wersja 4.6 ma nową funkcję, -debug, która zrzuca skrypt i dodaje adnotacje do linii wyjściowych. Pozwoliłoby to na tłumaczenie skryptów sed generowanych przez funkcje w bashu do postaci kanonicznej. Fajnie! Tylko nie zapomnij, że potrzebujesz rozgałęziania wersji sed w bashu. I tu właśnie w grę wchodzi ten przykład sed.

Przykładowa funkcja bash używająca sed do usuwania znaczników HTML

W powyższych przykładach znajduje się linia do usuwania znaczników HTML. Wrzućmy to do funkcji basha i użyjmy jej do usunięcia wszystkich znaczników HTML z ostatniego artykułu, który napisałem.

Komendy

strip-tags ()
{
sed -e 's/<*.//g' –
}
curl https://linuxhint.com/bash_cut_command/ –silent | strip-tags

Nie mogę powiedzieć, że jest to idealne, ale przynajmniej jest czytelne w terminalu.

Sed przykłady z workflow: Przykładowy workflow: bezpiecznie zastąp wszystko używając find, grep, i sed

Bezpiecznie jest powiedzieć, że zmiany dokonane przy użyciu sed z opcją -i są nieodwracalne. To znaczy, jeśli nie jesteś całkowicie pewien jaki tekst ma być zastąpiony, prawdopodobnie skończysz z jednym znakiem mniej niż zamierzałeś. Dlatego w tym przykładzie, użyjemy sed w przepływie pracy, aby bezpiecznie zastąpić tekst we wszystkich plikach, które wybrałeś.

Przepływ pracy

  1. find
  2. grep
  3. sed
find

W tym miejscu wybierzesz pliki, które mają zostać zastąpione. Sugeruję użycie polecenia o następującej treści:

find -type f -name | grep -v -e | xargs -i …

Na przykład, możesz chcieć ograniczyć pliki do zastąpienia plików PHP z wyłączeniem katalogów repozytorium git w następujący sposób.

find -type f -name \P.php | grep -v -e '.git' | xargs -i …

Poznaj więcej na temat polecenia xargs w bashu.

grep

Następnie, spróbujemy dopasować jakiś_wzór w plikach wybranych w następujący sposób. Zauważ, że ponieważ używamy opcji -o dla grep, wyjście pokaże tylko dopasowany łańcuch, jeśli taki istnieje.

find -type f -name \*.php | grep -v -e '.git' |
xargs -i grep -e some_pattern -o

Powyższe polecenie powinno zwrócić listę łańcuchów pasujących do some_pattern.

sed

W końcu chcemy zastąpić wszystkie łańcuchy pasujące do some_pattern. Aby to zrobić, musimy zamienić grep na sed w następujący sposób.

find -type f -name \*.php | grep -v -e '.git' |
xargs -i sed -i -e s/some_pattern/replacement/g

Komenda grep staje się sed -i, a opcja -o zostaje usunięta. I proszę bardzo.

Teraz możesz sprawdzić jakie łańcuchy zostaną zastąpione w sed zamiast testować swoje szczęście.

Przypisy dotyczące opcji użytych w przykładach

Tutaj znajduje się lista opcji użytych w przykładach sed omówionych pokrótce.

Opcja Opis
-.i Edytuj w miejscu. Jeśli dane wejściowe są plikami (nie piped in), wyniki wyrażeń będą nadpisywać zawartość pliku.

Sed akceptuje jeden

eg) sed -n …

-e -e oznacza wyrażenie. Jego parametrem jest wyrażenie w języku sed.

Sed akceptuje wiele

eg) sed -e 'expr1′ -e 'expr2′ …

-n Ukrywa linię, na którą nie ma wpływu wyrażenie. To znaczy, jeśli wyrażenie jest instrukcją print w języku sed, to linie nie zawarte w instrukcji print nie zostaną uwzględnione na wyjściu.

eg) sed -n …

Więcej na temat dostępnych opcji sed, zobacz sed -help

Uwagi końcowe na temat równoważnych poleceń używanych w przykładach

W przykładach sed z równoważnymi poleceniami występują następujące narzędzia wiersza poleceń.

  • sort
  • head
  • tail
  • grep
  • cat
  • Tr
  • tee

Uwaga końcowa na temat powłóczystego – w przykładowych równoważnych poleceniach

W przypadku gdy zastanawiasz się co się dzieje ze znakiem – w przykładzie, ta uwaga jest dla Ciebie. Dodałem znak – po większości komend w przykładach, aby podpowiedzieć, że oczekujemy, że dane wejściowe zostaną odebrane przez potok. Czyli,

cat some-file | sort -R – | head -1

Jednakże, gdy po lewej stronie znajduje się polecenie z potokiem, możemy pominąć podpowiedź w następujący sposób.

cat some-file | sort -R | head -1

Tak właśnie było ze znakiem – po poleceniach w przykładach.

Przypisy końcowe dotyczące funkcji do setup

Na wypadek gdybyś szukał, oto funkcje do setup dla powyższych przykładów. Dane wyjściowe uzyskane przy użyciu declare -f. Przeczytaj więcej o poleceniu declare w bashu, by dowiedzieć się więcej o jego zastosowaniach.

Komendy

words ()
{
seq 100
}
bar ()
{
echo —
}
old-php ()
{
echo 'ereg($UA, „Bottybot”)'
}

Podsumowanie

Bawiło mnie pisanie przykładów Bash sed, a nawet podniosłem kilka dodatkowych sztuczek po drodze. Sed jest potężnym narzędziem wiersza poleceń i ekspresyjnym językiem do manipulowania plikami tekstowymi. Jeśli podobała ci się nauka o sed, nie martw się, że jest jeszcze wiele do omówienia. Sed on.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *