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/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 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.