Jak znaleźć i zamienić ciąg bez użycia polecenia Sed?

Jak wszyscy wiemy, sed jest bardzo skutecznym narzędziem do znajdowania i zastępowania ciągu znaków, na przykład znajdź „a” i zamień go na „b”: sed "s/a/b/g".

Czy można to zrobić za pomocą innego polecenia lub skryptu powłoki zamiast sed?

To jest dla przyciętych systemów linuxowych dla TV, które nie mają polecenia sed. Muszę więc używać innych poleceń lub skryptów zamiast sed "s/a/b/g". –

Komentarze

  • Właściwie to jest po prostu podstawienie oparte na wyrażeniach regularnych. Każde narzędzie lub język zdolny do obsługi takich rzeczy będzie w stanie zrobić to samo, ale z różną składnią: $var=~s/a/b/g, gsub(/a/,"b",var), var.gsub(/a/,'b'), var.replace(/a/g,'b'), preg_replace("/a/","b",$var), regsub -all a b $var. Poza tym wiele narzędzi i języków może również zastępować zwykły ciąg tekstowy. Twoje pytanie jest więc szerokie.
  • Dlaczego? Jaki problem próbujesz rozwiązać?
  • Przycięty system Linux dla telewizji nie ma polecenia sed. Dlatego muszę użyć innego polecenia lub skryptu zamiast sed ' s / a / b / g '.

Odpowiedź

Tak, można to zrobić na wiele sposobów. Możesz również użyć awk, perl lub bash, aby wykonać te czynności. Ogólnie rzecz biorąc, sed jest prawdopodobnie najbardziej odpowiednim narzędziem do wykonywania tego typu zadań.

Przykłady

Powiedzmy, że mam te przykładowe dane, w pliku data.txt:

foo bar 12,300.50 foo bar 2,300.50 abc xyz 1,22,300.50 

awk

$ awk "{gsub("foo", "foofoofoo", $0); print}" data.txt foofoofoo bar 12,300.50 foofoofoo bar 2,300.50 abc xyz 1,22,300.50 

Perl

$ perl -pe "s/foo/foofoofoo/g" data.txt foofoofoo bar 12,300.50 foofoofoo bar 2,300.50 abc xyz 1,22,300.50 

Edycja bezpośrednia

Powyższe przykłady mogą również bezpośrednio modyfikować pliki. Przykład Perla jest trywialny. Po prostu dodaj przełącznik -i.

$ perl -pie "s/foo/foofoofoo/g" data.txt 

Dla awk to „jest trochę mniej bezpośredni, ale równie skuteczny:

$ { rm data.txt && awk "{gsub("foo", "foofoofoo", $0); print}" > data.txt; } < data.txt 

Ta metoda tworzy podpowłokę z nawiasami klamrowymi” {…} „w miejscu, w którym znajduje się plik przekierowany do niego przez to:

$ { ... } < data.txt 

Po przekierowaniu pliku do podpowłoki jest on usuwany, a następnie awk jest uruchamiany z zawartością pliku, który został wczytany do podpowłok STDIN. Ta zawartość jest następnie przetwarzana przez awk i zapisywana z powrotem do tej samej nazwy pliku że właśnie usunęliśmy, skutecznie je zastępując.

Komentarze

  • Dziękuję za odpowiedź i spróbuję następnego dnia roboczego. Ale nie jestem pewien, czy działa, ponieważ niektóre polecenia mogą nie istnieć w przyciętych systemach telewizyjnych linux, na przykład ' sed '. Więc nadal chcę używać polecenie ' find ', ' grep ' i tak dalej, aby go rozwiązać.
  • @binghenzq – I ' dodałem przykłady, które edytują plik bezpośrednio.
  • -1 Rzadko głosuję przeciw, ale w tym przypadku chodzi o pytanie wydawało się być prostszą metodą, a nie inną, bardziej / równie złożoną i prawdopodobnie również zależną. Gdyby pytanie dotyczyło tylko alternatyw dla pełnej instalacji maszyny * nix, prawdopodobnie dałbym +1 tej dobrej odpowiedzi.
  • @MichaelDurrant – właśnie dodałem te skomplikowane edycje w wierszu b / c, o które poprosił OP . Również OP ustawił wymóg NIE używając sed, a nie I. Sed jest odpowiednim narzędziem do wykonywania takich podstawień, a on ' najwyraźniej prosząc o lepsze zrozumienie roli tych narzędzi, więc pokazanie komuś tych rzeczy, chociaż są złe, jest niezwykle pouczające, pokazując, dlaczego. Zbyt często osoby, które wiedzą, po prostu powiedz ” don ' t zrób to ” bez wyjaśnienia dlaczego, więc jestem. Ale dziękuję, że przynajmniej zostawiłeś komentarz wyjaśniający, dlaczego jesteś DV.
  • Jasne, pomyślałem, że to świetna odpowiedź pod każdym innym względem. tak, nienawidzę -1 bez wyjaśnienia.

Odpowiedź

Klasyczną alternatywą dla podstawień jednoliterowych jest tr polecenie, które powinno być dostępne w prawie każdym systemie:

$ echo "foobar" | tr a b foobbr 

tr jest lepszy niż sed, ponieważ używa sed (nie mówiąc już o perl lub awk) do podstawiania pojedynczymi literami jest jak użycie młotka do zabicia muchy.

grep nie jest do tego przeznaczony, nie modyfikuje danych wejściowych, a jedynie je przeszukuje.

Alternatywnie, możesz użyć możliwości zastępowania niektórych powłok. Tutaj używając składni ksh, zsh lub bash:

$ foo="foobar" $ echo "${foo//a/b}" foobbr 

Moglibyśmy udzielić Ci bardziej szczegółowych odpowiedzi, gdybyś dokładnie wyjaśnił, jaki problem próbujesz rozwiązać.

Komentarze

  • Czy istnieje opcja ignorowania wielkości liter w ${foo//a/b}?
  • @ AlikElzin-kilaka I ' obawiam się nie. ' Będziesz musiał użyć czegoś bardziej wyrafinowanego, na przykład: echo "$foo" | sed 's/a/b/i lub nadać klasę znaków: echo ${foo//[aA]/b}.

Odpowiedź

Możesz użyć narzędzia POSIX ex:

ex a.txt <<eof %s/Sunday/Monday/g xit eof 

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html

Komentarze

  • wielkie dzięki. aby dodać, flaga -c oznacza wykonanie polecenia na początku edycji (ponieważ ex jest edytorem), a flaga -s jest albo trybem skryptu wyłączającym sprzężenie zwrotne, albo, jak niektórzy mówią, trybem slient. ref, aby uzyskać więcej informacji: ex-vi.sourceforge.net/ex.html

Odpowiedź

Jeśli pracujesz z plikiem, a nie strumieniem, możesz użyć standardowego edytora tekstu, ed:

printf "%s\n" ",s/a/b/g" w q | ed file.txt 

Powinien być dostępny na dowolnym * nix. Przecinek w ",s/a/b/g" informuje ed do pracy z każdą linią (możesz też użyć %, który będzie bardziej znany, jeśli „byłeś przyzwyczajony do vima), a reszta z tego to standardowe wyszukiwanie i zamiana. w każe mu zapisać (zapisać) plik, q każe mu wyjść.

Zauważ, że w przeciwieństwie do sed „s -i (i podobne opcje w innych narzędziach), to faktycznie powoduje edycję pliku na miejscu, zamiast oszukiwać z plikami tymczasowymi.

Nie „nie sądzę”, żeby to działało ze strumieniami, ale tak naprawdę nie wiem zbyt wiele o ed i nie zdziwiłbym się, gdyby rzeczywiście miał taką możliwość (filozofia unixa jest tym, czym jest).

Odpowiedź

Korzystanie z przodka polecenie (w którym -s oznacza cicho (cicho), a przecinek przed poleceniem oznacza wykonanie we wszystkich wierszach):

Po prostu drukowanie na STDOUT :

ed -s file <<! ,s/a/b/g ,p q ! 

zastępowanie w miejscu:

ed -s file <<! ,s/a/b/g w q ! 

Dodaj komentarz

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