-
-
Save jcamenisch/1671995 to your computer and use it in GitHub Desktop.
gg_replace() { | |
if [[ "$#" == "0" ]]; then | |
echo 'Usage:' | |
echo ' gg_replace term replacement file_mask' | |
echo | |
echo 'Example:' | |
echo ' gg_replace cappuchino cappuccino *.html' | |
echo | |
else | |
find=$1; shift | |
replace=$1; shift | |
ORIG_GLOBIGNORE=$GLOBIGNORE | |
GLOBIGNORE=*.* | |
if [[ "$#" = "0" ]]; then | |
set -- ' ' $@ | |
fi | |
while [[ "$#" -gt "0" ]]; do | |
for file in `git grep -l $find -- $1`; do | |
sed -e "s/$find/$replace/g" -i'' $file | |
done | |
shift | |
done | |
GLOBIGNORE=$ORIG_GLOBIGNORE | |
fi | |
} | |
gg_dasherize() { | |
gg_replace $1 `echo $1 | sed -e 's/_/-/g'` $2 | |
} |
zh4ngx
commented
Jun 12, 2012
via email
Oh, no, that's a different topic. The -i''
is hard-coded, and not affected by arguments you pass into gg_replace.
The third gg_replace argument (file mask) is for filtering what files you want to affect. So, if you only want to do a replacement in .html files, you can provide \*.html
. Or you can leave out the mask, and affect every file in the repository.
Now I'm going to have to document it better. :)
Right, sed does no backup with -i''
. I figured since this whole script does nothing outside a Git repo, sed's backup would be rather superfluous.
I do find it useful to run git diff
after executing this. That let's me quickly scan for anything that's not what I really intended.
So glad it's working for you! Thanks for helping make it a bit more robust. Now when I try it from a Linux server, it should just work.
...and make it so SEO-friendly (or maybe that was happy accident)
right on. :)
This is where I keep it: https://github.com/jcamenisch/dotfiles/blob/master/.profile
Uh, yeah. I've read about the difference, but I'd have to look it up to remember, of course. The reason I use .profile is that I've moved to zsh, but want to use all the same stuff for times when I'm on bash, including on other machines like web servers. So I just call .profile from .bashrc and .zshrc.
Is if-shell
the right way to do an OS conditional, like so?
ChrisJohnsen/tmux-MacOSX-pasteboard#8
That appears to be tmux-specific.
uname
with no parameters is very consistent across Unix and Linux variants. It provides an OS name like "Darwin" or "Linux". I use that at https://github.com/jcamenisch/dotfiles/blob/master/.profile#L14 to include OS-specific configurations from a separate file (when it exists). This one command lets me provide custom config files targeting as many different operating systems as I want, although .profile_Darwin is the only one I actually have so far.
I guess the more direct way of doing that--with no external script file--would be with
if [[ `uname` = Linux ]]; then
...
fi
or for one-line shorthand:
[[ `uname` = Linux ]] && ...
(Warning: my sh syntax is likely to be wrong when I write something and don't test it.)
True. But you can link to a fork if you have a recommended change. Copy/paste isn't too much work with this amount of code.
This is awesome. Thanks :)
Great to hear. Thanks!
Here's a case-insensitive version:
gg_ireplace() {
if [[ "$#" == "0" ]]; then
echo 'Usage:'
echo ' gg_ireplace term replacement file_mask'
echo
echo 'Example:'
echo ' gg_ireplace cappuccino Cappuccino *.html'
echo
else
find=$1; shift
replace=$1; shift
ORIG_GLOBIGNORE=$GLOBIGNORE
GLOBIGNORE=*.*
if [[ "$#" = "0" ]]; then
set -- ' ' $@
fi
while [[ "$#" -gt "0" ]]; do
for file in `git grep -Fil $find -- $1`; do
perl -pi -w -e "s/\Q$find\E/$replace/gi;" $file
done
shift
done
GLOBIGNORE=$ORIG_GLOBIGNORE
fi
}
Note the following, you may want to update your original script:
- Perl used for the regex, which allows for case-insensitive option
i
- Perl has
\Q...\E
, which allows us to make the$find
match literal - Usage of
git grep -F
for fixed-length string matching, makes initial search a bit faster
Also note that BSD sed command does not support the i
option... I don't know if there is any way to do this without Perl.
Odd, I get (on Mac) sed: -i may not be used with stdin
. Changing -i''
to -i ''
(with a space) fixes this, which makes sense: -i''
is exactly equivalent to -i
, I think, so it's treating $file
as the extension.
Here is my version that I use on Mac that handles filenames with 'Spaces'.
gg_replace() {
if [[ "$#" == "0" ]]; then
echo 'Usage:'
echo ' gg_replace term replacement file_mask'
echo
echo 'Example:'
echo ' gg_replace cappuchino cappuccino *.html'
echo
else
find=$1; shift
replace=$1; shift
ORIG_GLOBIGNORE=$GLOBIGNORE
GLOBIGNORE=*.*
if [[ "$#" = "0" ]]; then
set -- ' ' $@
fi
while [[ "$#" -gt "0" ]]; do
for file in `git grep -l $find -- $1 | sed -e "s/ /~~~~~/g"`; do
sed -i "" -e "s/$find/$replace/g" "${file/~~~~~/ }"
done
shift
done
GLOBIGNORE=$ORIG_GLOBIGNORE
fi
}
just a small tip for those trying to use this on OS X: install GNU sed (brew install gnu-sed
) and replace the sed
call with gsed
Here's my version: https://gist.github.com/glyph/9beafa8a7b26e5ca9f6666448fa5810d
gg_replace() {
if [[ "$#" -lt "2" ]]; then
echo "
Usage:
$0 term replacement file_mask
Example:
$0 cappuchino cappuccino '*.html'
";
else
local find="$1"; shift;
local replace="$1"; shift;
git grep -zlI "${find}" -- "$@" |
xargs -0 sed -e "s/${find}/${replace}/g" -i '' ;
fi;
}
A few notes:
- passes shellcheck
- doesn't depend on word splitting so doesn't need to monkey with
GLOBIGNORE
- supports spaces, newlines, and (apropos of dawalama's version ;-))
~~~~~
in path names - it still has the problem described in dwheeler's https://dwheeler.com/essays/filenames-in-shell.html section 3.3, since I couldn't figure out a quick way to make
git grep
prefix all its output with./
- it's a bit faster since it doesn't spawn new
sed
processes quite so many times