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
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/ilub 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 ed 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 !
$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.