904 Stimmen

Wie kann ich ein rekursives Suchen/Ersetzen einer Zeichenkette mit awk oder sed durchführen?

Wie finde und ersetze ich jedes Vorkommen von:

subdomainA.example.com

mit

subdomainB.example.com

in jeder Textdatei unter dem /home/www/ Verzeichnisbaum rekursiv?

114 Stimmen

Tipp: Führen Sie die folgenden Schritte nicht in einem svn-Checkout-Baum durch... es wird die magischen .svn-Ordnerdateien überschreiben.

9 Stimmen

Oh mein Gott, das ist genau das, was ich gerade getan habe. Aber es hat funktioniert und es scheint keinen Schaden angerichtet zu haben. Was könnte schlimmstenfalls passieren?

5 Stimmen

@J.Katzwinkel: Zumindest können die Prüfsummen beschädigt werden, was wiederum Ihr Repository beschädigen kann.

2voto

Sheena Punkte 14544
perl -p -i -e 's/oldthing/new_thingy/g' `grep -ril oldthing *`

1 Stimmen

Nicht verwenden awk / sed , aber Perl ist weit verbreitet (außer bei eingebetteten Systemen / Systemen mit Busybox).

0 Stimmen

Dies funktioniert nicht bei Dateien, deren Namen Leerzeichen oder neue Zeilen enthalten

2voto

Johnny Utahh Punkte 2219

Ersetzen von find(1) mit dem einfacheren fd(1) / fdfind = https://github.com/sharkdp/fd :

fdfind . --type f --exec sed -i "s/original_string/new_string/g"

Adressierung fd(1) iconsistent pkg & cmd Namen

  • unter macOS homebrew: pkg und cmd = fd
  • auf Ubuntu 20.04: pkg = fd-find , cmd = fdfind

Ich mache eine alias fdfind='fd' auf macOS für eine einheitliche cmd-Benennung (zwischen meinen macOS- und Linux-Plattformen).

Mehr zu diesem Thema unter https://github.com/sharkdp/fd/issues/1009 .

Weitere Details und zusätzliche Funktionen

# bash examples:

1='original_string'
2='new______string'

# for this (the original-poster's) question:
1='subdomainA.example.com'
2='subdomainB.example.com'

# 'fdfind' (on at least Ubuntu 20.04) = 'fd' = https://github.com/sharkdp/fd

fdfind . --type f --exec sed -i "s/$1/$2/g"

# Here's a slightly-more-complex example that
# a. excludes (-E) .git/ and archive/ dirs, and
# b. performs a word-boundary search on the original_string (\<$1\>):
fdfind . -E .git/ -E archive/ --type f --exec sed -i "s/\<$1\>/$2/g"

Noch ausgefallener: die Kontrolle der Wortgrenzen vom dritten ( $3 ) Befehlszeilen-Parameter (dritter Parameter = noword bedeutet keine Begrenzung, leftword bedeutet nur linksseitige Wortgrenze, rightword bedeutet nur rechtsseitige Begrenzung):

#!/usr/bin/env bash

#
# replace-tree.bash
#

# 'fdfind' (on at least Ubuntu 20.04) = 'fd' = https://github.com/sharkdp/fd

if [ $# -lt 2 ]; then
  echo "$0: Please provide at least 2 arguments."
  exit 1
fi

original="\<$1\>"

if   [ "$3" = "noword" ];    then
  original="$1"
elif [ "$3" = "leftword" ];  then
  original="\<$1"
elif [ "$3" = "rightword" ]; then
  original="$1\>"
fi

fdfind . --type f --exec sed -i "s/$original/$2/g"

Beispiel für die Verwendung:

$ replace-tree.bash original_string new_string leftword
$

1voto

mathiasrw Punkte 600

Wenn Sie Zugang zu Node haben, können Sie eine npm install -g rexreplace und dann

rexreplace 'subdomainA.example.com' 'subdomainB.example.com' /home/www/**/*.*

1voto

Klas. S Punkte 620

So ersetzen Sie alle übereinstimmenden Inhalte string_1 con string_2 von allen .c y .h Dateien im aktuellen Verzeichnis und in den Unterverzeichnissen (außer .git/) .

Dies funktioniert bei Mac :

find . -type f -path "*.git*" -prune -o -name '*\.[ch]' -exec \
sed -i '' -e 's/'$1'/'$2'/g' {} +

Dies sollte funktionieren bei Linux (Wurde noch nicht getestet):

find . -type f -path "*.git*" -prune -o -name '*\.[ch]' -exec \
sed -i 's/string_1/string_2/g' {} +

1voto

cchamberlain Punkte 15982

Dies ist die beste Allround-Lösung, die ich für OSX und Windows (msys2) gefunden habe. Sollte mit allem funktionieren, das die gnu-Version von sed nutzen kann. Überspringt die .git-Verzeichnisse, so dass es nicht Ihre Prüfsummen beschädigt.

Auf dem Mac installieren Sie zuerst coreutils und stellen Sie sicher, dass gsed im Pfad enthalten ist -

brew install coreutils

Dann füge ich diese Funktion in meine zshrc/bashrc ein ->

replace-recursive() {
    hash gsed 2>/dev/null && local SED_CMD="gsed" || SED_CMD="sed"
    find . -type f -name "*.*" -not -path "*/.git/*" -print0 | xargs -0 $SED_CMD -i "s/$1/$2/g"
}

usage: replace-recursive <find> <replace>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X