Předpokládejme, že mám soubor, který obsahuje více výskytů StringA i StringB. Chci nahradit všechny výskyty StringA StringB a (současně) všechny výskyty StringB řetězcem StringA.
Právě teď dělám něco jako
cat file.txt | sed 's/StringB/StringC/g' | sed 's/StringA/StringB/g' | sed 's/StringC/StringA/g'
Problém s tímto přístupem je, že předpokládá, že StringC se v souboru nevyskytuje. I když to v praxi není problém, toto řešení je stále špinavé - to znamená, že to vypadá jako příležitost naučit se více unixové magie. 🙂
Přijatá odpověď:
Pokud StringB
a StringA
se nemůže objevit na stejném vstupním řádku, pak můžete říct sed, aby provedl nahrazení jedním způsobem, a zkuste to pouze jiným způsobem, pokud se nevyskytuje první hledaný řetězec.
<file.txt sed -e 's/StringA/StringB/g' -e t -e 's/StringB/StringA/g'
V obecném případě si nemyslím, že v sed existuje snadná metoda. Mimochodem, všimněte si, že specifikace je nejednoznačná, pokud StringA
a StringB
se může překrývat. Zde je řešení v Perlu, které nahradí výskyt jednoho řetězce zcela vlevo a opakuje.
<file.txt perl -pe 'BEGIN {%r = ("StringA" => "StringB", "StringB" => "StringA")}
s/(StringA|StringB)/$r{$1}/ge'
Pokud chcete zůstat u nástrojů POSIX, awk je správná cesta. Awk nemá primitivum pro obecné parametrizované náhrady, takže musíte hodit své vlastní.
<file.txt awk '{
while (match($0, /StringA|StringB/)) {
printf "%s", substr($0, 1, RSTART-1);
$0 = substr($0, RSTART);
printf "%s", /^StringA/ ? "StringB" : "StringA";
$0 = substr($0, 1+RLENGTH)
}
print
}'