Jak najít a nahradit řetězec bez použití příkazu Sed?

Jak všichni víme, sed je velmi efektivní najít a nahradit řetězec, například najít „a“ a nahraďte jej „b“: sed "s/a/b/g".

Je to možné pomocí jiného příkazového nebo shell skriptu místo sed?

Toto je pro oříznuté linuxové systémy pro TV, které nemají příkaz sed. Musím tedy místo sed "s/a/b/g". –

komentářů

  • ve skutečnosti použít jiné příkazy nebo skripty jen substituce založená na regulárním výrazu. Jakýkoli nástroj nebo jazyk schopný takové věci zvládnout, bude schopen udělat totéž, ale s různou syntaxí: $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. Kromě toho může mnoho nástrojů a jazyků také provádět výměnu řetězců prostého textu. Takže vaše otázka je nějak široká.
  • Proč? Jaký problém se snažíte vyřešit?
  • Oříznuté linuxové systémy pro TV nemají příkaz sed. Takže místo sed ' s / a / b / g ' musím použít jiný příkaz nebo skript.

Odpověď

Ano, existuje celá řada způsobů, jak toho dosáhnout. K provádění těchto činností můžete použít awk, perl nebo bash. Obecně je však sed nejvhodnějším nástrojem pro provádění těchto typů úkolů.

Příklady

Řekněme, že mám tato ukázková data, v souboru 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 

Přímé úpravy

Výše uvedené příklady mohou také přímo upravovat soubory. Příklad Perlu je triviální. Jednoduše přidejte přepínač -i.

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

Pro awk „je o něco méně přímý, ale stejně efektivní:

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

Tato metoda vytvoří dílčí shell se složenými závorkami“ {…} „, kde je soubor přesměrován do něj pomocí tohoto:

$ { ... } < data.txt 

Jakmile je soubor přesměrován do dílčího shellu, je smazán a poté awk je spuštěn proti obsahu souboru, který byl načten do dílčích skořápek STDIN. Tento obsah je poté zpracován programem awk a zapsán zpět na stejný název souboru kterou jsme právě smazali, a účinně ji nahradíme.

Komentáře

  • Děkuji za odpověď a zkusím to příští pracovní den. Nejsem si však jistý, jestli funguje to, protože nějaký příkaz nemusí v oříznutých linuxových systémech televize existovat, například ' sed '. Takže chci i nadále používat příkaz ' najít ', ' grep ' a tak dále.
  • @binghenzq – Přidal jsem ' příklady, které inline upravují soubor.
  • -1 Zřídka hlasuji, ale v tomto případě jde o otázka se zdála být spíše jednodušší metodou než jinou více / stejně složitou a pravděpodobně také závislou. Pokud by otázka byla jen o alternativách pro úplnou instalaci stroje * nix, pak bych pravděpodobně dal +1 této jinak dobré odpovědi.
  • @MichaelDurrant – právě jsem přidal ty komplikované inline úpravy b / c, které o ně OP požádal . Také OP nastavil požadavek na NE používání sed ne I. Sed je vhodný nástroj pro provádění takových substitucí a on ' očividně žádá o lepší pochopení rolí těchto nástrojů, takže ukázat někomu tyto věci, i když jsou špatné, je nesmírně poučné ukázat jim proč. Příliš mnohokrát ppl ve znalostech jednoduše řekne " don ' nedělat to " aniž bych vysvětlil proč, tak jsem. Ale díky za alespoň zanechání komentáře, proč jste DV.
  • Jistě, myslel jsem si, že je to skvělá odpověď ve všech ostatních ohledech. jo, nesnáším -1 bez vysvětlení.

odpověď

Klasickou alternativou pro nahrazení jedním písmenem je tr příkaz, který by měl být k dispozici téměř v každém systému:

$ echo "foobar" | tr a b foobbr 

tr je lepší než sed, protože použití sed (natož perl nebo awk) pro nahrazení jedním písmenem je jako použití kladiva k zabití mouchy.

grep k tomu není určen, nemění svůj vstup, pouze v něm prohledává.

Alternativně můžete použít možnosti nahrazení některých skořápek. Zde pomocí ksh, zsh nebo bash syntaxe:

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

Mohli bychom vám dát konkrétnější odpovědi, pokud byste přesně vysvětlili, jaký problém se snažíte vyřešit.

Komentáře

  • Existuje možnost ignorovat velká písmena v ${foo//a/b}?
  • @ AlikElzin-kilaka I ' se bojím ne. Musíte ' použít něco sofistikovanějšího typu, například: echo "$foo" | sed 's/a/b/i nebo zadat třídu znaků: echo ${foo//[aA]/b}.

Odpověď

Můžete použít nástroj POSIX ex:

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

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

Komentáře

  • skvělé díky. stačí přidat, příznak -c znamená provést příkaz při zahájení editace (protože ex je editor) a příznak -s je buď režim skriptu zakazující zpětnou vazbu, nebo jak někteří říkají režim klienta. ref for more info: ex-vi.sourceforge.net/ex.html

Odpověď

Pokud pracujete spíše se souborem než se streamem, můžete použít standardní textový editor ed:

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

To by mělo být k dispozici na libovolném * nix. Čárka v ",s/a/b/g" říká ed pro práci na každém řádku (můžete také použít %, který bude známější, pokud jste zvyklí na vim), a zbytek z toho je standardní vyhledávání a nahrazování. w říká, že má soubor zapsat (uložit), q mu říká, že má skončit.

Všimněte si, že na rozdíl od možnost sed „s -i (a podobné možnosti v jiných nástrojích), ve skutečnosti soubor upraví na místě, místo aby jej podváděl dočasnými soubory.

„Nemyslím si, že je to možné, aby to fungovalo se streamy, ale pak toho o ed moc nevím a nepřekvapilo by mě, kdyby skutečně tuto schopnost měl (unixová filozofie je tím, čím je).

Odpověď

Použití předchůdce (ve kterém -s znamená tichý (tichý) a čárka před příkazy znamená provedení na všech řádcích):

Jen tisk na STDOUT :

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

nahrazení na místě:

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

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *