Size: 3137
Comment: remove typos i introduced
|
Size: 3395
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
[[Anchor(faq21)]] | <<Anchor(faq21)>> |
Line 8: | Line 8: |
'''Note that input and output must differ.'' | |
Line 23: | Line 24: |
On *BSD, sed has a {{{-i}}} flag as well, but it takes a mandatory argument. The above example then becomes | On some (but not all) BSD systems, sed has a {{{-i}}} flag as well, but it takes a mandatory argument. The above example then becomes |
Line 29: | Line 30: |
which in turn does not work with GNU sed. Effectively, whenever portability matters, -i should be avoided. | which in turn does not work with GNU sed. Effectively, whenever portability matters, {{{sed -i}}} should be avoided. |
Line 43: | Line 44: |
If you want to delete lines instead of making substitutions: {{{ perl -ni -e 'print unless /foo/' * # Deletes any line containing the perl regex foo }}} |
|
Line 49: | Line 57: |
Line 86: | Line 93: |
* the {{{find}}} command above could use either {{{xargs}}} or the built-in {{{xargs}}} of POSIX find | * the [[UsingFind|find]] command above could use either {{{xargs}}} or the built-in {{{xargs}}} of POSIX find |
How can I replace a string with another string in all files?
sed is a good command to replace strings, e.g.
sed 's/olddomain\.com/newdomain.com/g' input > output
Note that input and output must differ. To replace a string in all files of the current directory: GNU sed 4.x has a special -i flag which makes the loop and temp file unnecessary: On some (but not all) BSD systems, sed has a -i flag as well, but it takes a mandatory argument. The above example then becomes which in turn does not work with GNU sed. Effectively, whenever portability matters, sed -i should be avoided. Those of you who have perl 5 can accomplish the same thing using this code: Recursively (requires GNU or BSD find): If you want to delete lines instead of making substitutions: To replace for example all "unsigned" with "unsigned long", if it is not "unsigned int" or "unsigned long" ...: Finally, for those of you with If the code above is put into a script file (e.g. chtext), the resulting script can be used to change a text e.g. in all HTML files of the current and all subdirectories: Many optimizations are possible: use another sed separator character than '|', e.g. ^A (ASCII 1) the find command above could use either xargs or the built-in xargs of POSIX find Note: set -- * in the code above is safe with respect to files whose names contain spaces. The expansion of * by set is the same as the expansion done by for, and filenames will be preserved properly as individual parameters, and not broken into words on whitespace. A more sophisticated example of chtext is here: http://www.shelldorado.com/scripts/cmds/chtext for i in *; do
sed 's/old/new/g' "$i" > atempfile && mv atempfile "$i"
done
sed -i 's/old/new/g' *
sed -i '' 's/old/new/g' *
perl -pi -e 's/old/new/g' *
find . -type f -print0 | xargs -0 perl -pi -e 's/old/new/g'
perl -ni -e 'print unless /foo/' *
# Deletes any line containing the perl regex foo
find . -type f -print0 | xargs -0 perl -i.bak -pne \
's/\bunsigned\b(?!\s+(int|short|long|char))/unsigned long/g'
#!/bin/sh
# chtext - change text in several files
# neither string may contain '|' unquoted
old='olddomain\.com'
new='newdomain\.com'
# if no files were specified on the command line, use all files:
[ $# -lt 1 ] && set -- *
for file
do
[ -f "$file" ] || continue # do not process e.g. directories
[ -r "$file" ] || continue # cannot read file - ignore it
# Replace string, write output to temporary file. Terminate script in case of errors
sed "s|$old|$new|g" "$file" > "$file"-new || exit
# If the file has changed, overwrite original file. Otherwise remove copy
if cmp "$file" "$file"-new >/dev/null 2>&1
then rm "$file"-new # file has not changed
else mv "$file"-new "$file" # file has changed: overwrite original file
fi
done
find . -type f -name '*.html' -exec chtext {} \;