Při práci s textovými soubory budete často muset najít a nahradit textové řetězce v jednom nebo více souborech.
sed
je s tream ed itor. Může provádět základní manipulaci s textem na souborech a vstupních proudech, jako jsou potrubí. Pomocí sed
, můžete vyhledávat, hledat a nahrazovat, vkládat a odstraňovat slova a řádky. Podporuje základní a rozšířené regulární výrazy, které vám umožňují porovnat složité vzory.
V tomto článku si povíme, jak najít a nahradit řetězce pomocí sed
. Také vám ukážeme, jak provádět rekurzivní vyhledávání a nahrazování.
Najít a nahradit řetězec řetězcem sed
#
Existuje několik verzí sed
s některými funkčními rozdíly mezi nimi. macOS používá verzi BSD, zatímco většina distribucí Linuxu přichází s GNU sed
ve výchozím nastavení předinstalovaný. Použijeme verzi GNU.
Obecná forma vyhledávání a nahrazování textu pomocí sed
má následující tvar:
sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE
-i
– Ve výchozím nastavenísed
zapíše svůj výstup na standardní výstup. Tato možnost říkásed
upravovat soubory na místě. Pokud je dodaná přípona (ex -i.bak), vytvoří se záloha původního souboru.s
- Náhradní příkaz, pravděpodobně nejpoužívanější příkaz v sed./ / /
- Oddělovací znak. Může to být jakýkoli znak, ale obvykle lomítko (/
) se používá.SEARCH_REGEX
- Normální řetězec nebo regulární výraz k vyhledání.REPLACEMENT
- Náhradní řetězec.g
- Globální vlajka nahrazení. Ve výchozím nastavenísed
přečte soubor řádek po řádku a změní pouze první výskytSEARCH_REGEX
na lince. Když je poskytnut příznak nahrazení, všechny výskyty jsou nahrazeny.INPUTFILE
- Název souboru, na kterém chcete spustit příkaz.
Je dobrým zvykem umístit argument do uvozovek, aby se metaznaky shellu nerozšiřovaly.
Podívejme se, jak můžeme použít sed
příkaz k vyhledání a nahrazení textu v souborech některými z jeho nejběžněji používaných voleb a příznaků.
Pro demonstrační účely budeme používat následující soubor:
file.txt123 Foo foo foo
foo /bin/bash Ubuntu foobar 456
Pokud g
příznak je vynechán, nahradí se pouze první výskyt hledaného řetězce v každém řádku:
sed -i 's/foo/linux/' file.txt
123 Foo linux foo
linux /bin/bash Ubuntu foobar 456
S globálním příznakem nahrazení sed
nahradí všechny výskyty vyhledávacího vzoru:
sed -i 's/foo/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456
Jak jste si možná všimli, podřetězec foo
uvnitř foobar
řetězec je také nahrazen v předchozím příkladu. Pokud toto není požadované chování, použijte výraz na hranici slova (\b
) na obou koncích vyhledávacího řetězce. To zajistí, že se dílčí slova nebudou shodovat.
sed -i 's/\bfoo\b/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu foobar 456
Chcete-li, aby se ve vzoru nerozlišovala velká a malá písmena, použijte I
vlajka. V níže uvedeném příkladu používáme oba g
a I
příznaky:
sed -i 's/foo/linux/gI' file.txt
123 linux linux linux
linux /bin/bash Ubuntu linuxbar 456
Pokud chcete najít a nahradit řetězec, který obsahuje oddělovací znak (/
), budete muset použít zpětné lomítko (\
), abyste unikli lomítku. Například nahradit /bin/bash
pomocí /usr/bin/zsh
byste použili
sed -i 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txt
Jednodušší a mnohem čitelnější možností je použít jiný oddělovací znak. Většina lidí používá svislou čáru (|
) nebo dvojtečkou (:
), ale můžete použít jakýkoli jiný znak:
sed -i 's|/bin/bash|/usr/bin/zsh|g' file.txt
123 Foo foo foo
foo /usr/bin/zsh Ubuntu foobar 456
Můžete také použít regulární výrazy. Chcete-li například vyhledat všechna 3místná čísla a nahradit je řetězcem number
byste použili:
sed -i 's/\b[0-9]\{3\}\b/number/g' file.txt
number Foo foo foo
foo /bin/bash demo foobar number
Další užitečnou funkcí sed je, že můžete použít znak ampersand &
který odpovídá shodnému vzoru. Znak lze použít vícekrát.
Pokud například chcete přidat složené závorky {}
kolem každého 3místného čísla zadejte:
sed -i 's/\b[0-9]\{3\}\b/{&}/g' file.txt
{123} Foo foo foo
foo /bin/bash demo foobar {456}
V neposlední řadě je vždy dobré vytvořit zálohu při úpravě souboru pomocí sed
. Chcete-li to provést, stačí zadat příponu záložního souboru do -i
volba. Chcete-li například upravit soubor file.txt
a uložte původní soubor jako file.txt.bak
byste použili:
sed -i.bak 's/foo/linux/g' file.txt
Chcete-li se ujistit, že je záloha vytvořena, uveďte soubory s ls
příkaz:
ls
file.txt file.txt.bak
Rekurzivní hledání a nahrazení #
Někdy můžete chtít rekurzivně hledat v adresářích soubory obsahující řetězec a nahradit řetězec ve všech souborech. To lze provést pomocí příkazů jako find
nebo grep
k rekurzivnímu vyhledání souborů v adresáři a převedení názvů souborů do sed
.
Následující příkaz rekurzivně vyhledá soubory v aktuálním pracovním adresáři a předá názvy souborů do sed
.
find . -type f -exec sed -i 's/foo/bar/g' {} +
Chcete-li se vyhnout problémům se soubory obsahujícími mezeru v názvech, použijte -print0
volba, která říká find
vytiskne název souboru následovaný znakem null a výstup převede do sed
pomocí xargs -0
:
find . -type f -print0 | xargs -0 sed -i 's/foo/bar/g'
Chcete-li vyloučit adresář, použijte -not -path
volba. Pokud například nahrazujete řetězec v místním gitovém repozitáři, abyste vyloučili všechny soubory začínající tečkou (.
), použijte:
find . -type f -not -path '*/\.*' -print0 | xargs -0 sed -i 's/foo/bar/g'
Pokud chcete hledat a nahrazovat text pouze v souborech s konkrétní příponou, použijete:
find . -type f -name "*.md" -print0 | xargs -0 sed -i 's/foo/bar/g'
Další možností je použít grep
příkaz k rekurzivnímu vyhledání všech souborů obsahujících vyhledávací vzor a poté přesměrování názvů souborů do sed
:
grep -rlZ 'foo' . | xargs -0 sed -i.bak 's/foo/bar/g'
Závěr č.
I když se to může zdát komplikované a složité, zprvu hledání a nahrazování textu v souborech pomocí sed
je velmi jednoduché.
Chcete-li se dozvědět více o sed
příkazy, možnosti a příznaky naleznete v příručce sed GNU a výukovém programu sed Grymoire.
Pokud máte nějaké dotazy nebo zpětnou vazbu, neváhejte zanechat komentář.