Znajdź i zamień łańcuch we wszystkich plikach rekurencyjnie za pomocą grep i sed [duplikat]

To pytanie ma już odpowiedź tutaj:

I ' m getting a

sed: -e expression #1, char 22: unterminated `s' command 
Czy jest jakiś problem z moim scenariuszem? Również "oldstring" ma znaki specjalne
#!bin/bash
oldstring='<script>"[oldscript]"</script>'
newstring='<script>"[newscript]"</script>'
grep -rl $oldstring /path/to/folder | xargs sed -i s/$oldstring/$newstring/g
Author: Steven Penny, 2013-04-10

5 answers

Jak powiedział @Didier, możesz zmienić swój ogranicznik na coś innego niż /:

grep -rl $oldstring /path/to/folder | xargs sed -i s@$oldstring@$newstring@g
 37
Author: wudeng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-10 12:30:24
grep -rl $oldstring . | xargs sed -i "s/$oldstring/$newstring/g"
 12
Author: Sreedhar GS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-28 06:47:32

Chłopaki z GNU naprawdę namieszali, kiedy wprowadzili rekurencyjne wyszukiwanie plików do grepa. grep służy do znajdowania REs w plikach i drukowania pasującej linii (g/re / p).) Nie do znajdowania plików. Jest to bardzo dobre narzędzie o bardzo oczywistej nazwie do wyszukiwania plików. Co się stało z uniksową mantrą zrobić jedną rzecz i zrobić to dobrze?

W każdym razie, oto jak możesz zrobić to, co chcesz, używając tradycyjnego podejścia uniksowego (nieprzetestowanego):

find /path/to/folder -type f -print |
while IFS= read -r file
do
   awk -v old="$oldstring" -v new="$newstring" '
      BEGIN{ rlength = length(old) }
      rstart = index($0,old) { $0 = substr($0,rstart-1) new substr($0,rstart+rlength) }
      { print }
   ' "$file" > tmp &&
   mv tmp "$file"
done

Nie, że używając awk / index () zamiast w przypadku sed i grep unikasz konieczności ucieczki wszystkich METACHARAKTERÓW, które mogą pojawić się w starym lub nowym łańcuchu, a także wymyśl znak do użycia jako ogranicznik sed, który nie może pojawić się w starym lub nowym łańcuchu, i że nie musisz uruchamiać grepa, ponieważ zastąpienie nastąpi tylko dla plików, które zawierają żądany ciąg. Mimo wszystko, jeśli nie chcesz, aby znacznik czasu pliku zmieniał się, jeśli nie zmodyfikujesz pliku, po prostu zrób różnicę na tmp i oryginalny plik przed wykonaniem mv lub wrzucić fgrep-q przed awk.

Zastrzeżenie: powyższe nie będzie działać dla nazw plików zawierających nowe linie. Jeśli masz je, daj nam znać, a my pokażemy Ci, jak sobie z nimi radzić.

 5
Author: Ed Morton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-11 12:53:39

sed wyrażenie musi być cytowane

sed -i "s/$oldstring/$newstring/g"
 3
Author: Steven Penny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-10 08:21:06
grep -rl SOSTITUTETHIS . | xargs sed -Ei 's/(.*)SOSTITUTETHIS(.*)/\1WITHTHIS\2/g'
 -1
Author: Mok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-07 14:25:19