Find & Replace String in All Found Files with LaTeX $sim$ -> $\sim$ - regex

I know this sort of question has been asked many times before, but I'm running into an odd circumstance where my feeble brain forgot to include a \ while calling $\sim$ in some markdown files. I need to go through and replace all instances of $sim$ with $\sim$. My code is running but not actually replacing any of the words that I want. Here are some variations I have tried:
grep -rl '\$sim\$' . | xargs sed -i 's/\$sim\$/$\sim$/g'
grep -rlF '$sim$' . | xargs sed -i 's/\$sim\$/$\sim$/g'
grep -rlF '$sim$' . | xargs sed -i 's/$sim$/$\sim$/g'
grep -rlF '$sim$' . | xargs sed -i '' -e 's/$sim$/$\sim$/g'
And other odd variations on a theme. The code just runs with no output but when I check the files nothing has changed. I figure this is either a sed issue (I'm macOS) or a regex issue.

Like this :
grep -rlF '$sim$' | xargs sed -i 's/$sim\$/$\\sim$/g'
for MacOsX :
grep -rlF '$sim$' | xargs sed -i '' 's/$sim\$/$\\sim$/g'

sed -i changes files in place, however you aren't telling sed to operate on any files. You are giving sed its input on stdin.
What you want is something like
find . -type f -exec sed -i 's/\$sim\$/$\\sim\$/g' {} \;

Related

How to avoid temporary files in doing search/replace string in files

I was trying to search and replace string in files using command:
grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g'
The problem is, it reports error that temporary file $#^%$^$ cannot be opened: permission denied.
The command was run with sudo, so it seems the temporary file was generated when grep command is executed, but sed cannot replace the string in that temp file since it's being opened.
I tried to specify the file type to *.html but still the same error:
grep -rl oldtext *.html . | xargs sed -i 's/oldtext/newtext/g'
I know using find can avoid the issue:
find ./ -type f -exec sed -i -e 's/oldstring/newstring/g' *.html {} \;
Just curious how to avoid this issue with grep command. Thanks!

How can i replace the all email address found in particular folder in linux

I have some scripts in some folder. like /var/www/sites
Now i want to replace all the email address hardcoded in the scripts in all folders and subfolders and replace with my email address
how can i do that.
I can find using
grep -rn "abc#gmail.com" /var/www/sites/
But i don't know how to use regex and replace
Try perl:
perl -p -i -e 's/abc#gmail.com/new#gmail.com/g' /var/www/sites/*
Or with perl/find:
find /var/www/sites/ -exec perl -p -i -e 's/abc#gmail.com/new#gmail.com/g' {} \;
Open a shell, then
if you have bash4 :
oldmail="abc#gmail.com"
newmail="myemail#provider.tld"
shopt -s globstar
sed -i "/$oldmail/s/$oldmail/$newmail/g" /var/www/sites/**/*
if not :
oldmail="abc#gmail.com"
newmail="myemail#provider.tld"
find /var/www/sites -type f -exec sed -i "/$oldmail/s/$oldmail/$newmail/g" {} +
This solutions have the advantage to not modify the timestamps in the files even if the file doesn't contains the searched string, unlike sed -i & perl -i -pe solutions without a previous grep (I do this here with /pattern/)
find /var/www/sites -type f | xargs sed --in-place 's/abc#gmail\.com/mynewemail#elsewhere.com/g'
Try sed.
grep -rl "abc#gmail.com" /var/www/sites/ | xargs sed -i 's/oldemail/newemail/g'
Edit:
Took feedback into account. Sorry about the previously wrong solution!

How can I make this script more concise?

I wrote a little script which prints the names of files containing problematic character sequences.
#!/bin/bash
# Finds all files in the repository that contain
# undesired characters or sequences of characters
pushd .. >/dev/null
# Find Windows newlines
find . -type f | grep -v ".git/" | grep -v ".gitmodules" | grep -v "^./lib" | xargs grep -l $'\r'
# Find tabs (should be spaces)
find . -type f | grep -v ".git/" | grep -v ".gitmodules" | grep -v "^./lib" | xargs grep -l $'\t'
# Find trailing spaces
find . -type f | grep -v ".git/" | grep -v ".gitmodules" | grep -v "^./lib" | xargs grep -l " $"
popd >/dev/null
I'd line to combine this into one line, i.e. by having grep look for \r OR \t or trailing spaces. How would I construct a regex to do this? It seems that for escape characters a special sequence needs to be used ($'\X') and I'm not sure how to combine these...
I'm running OS X, and am looking for a solution that works on both BSD and GNU based systems.
find . -type f | grep -E -v ".git/|.gitmodules|^./lib" | xargs grep -E -l '$\r|$\t| $'
Not certain that '$\r|$\t| $' will work quoted that way, with a simple test on my system it seemed to work.
I'm using the -E (extended reg-exp) to grep, that allows 'OR'ing together multiple search targets.
Older Unix-en may or maynot support the -E option, so if you get an error message flagging that, replace all grep -E with egrep.
I hope this helps.

how can I make this sed capture accomplish a more complex substitution

when fixing mass spelling errors in my code base i have used this:
find . -path '*/.svn' -prune -o -name "*min.js" -prune -o -name "*min.css" -prune -o -name "flashLocaleXml.xml" -prune -o -type f -print0 | xargs -0 egrep -n "priority=" -exec sed -i 's/replace/newval/' {} \;
to fix a specific spelling error in all the files in my repo.
however, i am not very good with sed captures, i want to do something like:
X.addEventListener(LevelUpEvent.GENERIC_LEVEL_UP, updateLevels);
becomes:
EventUtil.addEventListener(X, LevelUpEvent.GENERIC_LEVEL_UP, updateLevels);
I have read up extensively but I would appreciate someone explaining how sed captures work with this as a specific example.
I have given it a few shots, but nothing I come up with works: here are my tries
echo "X.addEventListener(LevelUpEvent.GENERIC_LEVEL_UP, updateLevels);" | sed 's/\(.*\)EventUtil\(.*EventUtil\)/\1X\2/'
echo "X.addEventListener(LevelUpEvent.GENERIC_LEVEL_UP, updateLevels);" | sed -r 's/(....),(....),(*\.addEventListener)(LevelUpEvent.*)/\1,\2\n\1,\2,/g'
echo "X.addEventListener(LevelUpEvent.GENERIC_LEVEL_UP, updateLevels);" | sed 's/\([\.$]*\) \([\.$]*\)/\2 \1/'
thank you in advance!
Try with:
sed 's/\([^.]*\)\([^(]*(\)/EventUtil\2\1, /'
Output:
EventUtil.addEventListener(X, LevelUpEvent.GENERIC_LEVEL_UP, updateLevels);
Explanation:
\([^.]*\) # Content until first '.'
\([^(]*(\) # Content until first '('
EventUtil\2\1, # Literal 'EventUtil' plus grouped content in previous expression.
This sed command will do.
sed 's/\(X\).\(addEventListener\)(\(LevelUpEvent.GENERIC_LEVEL_UP, updateLevels\));/EventUtil.\2(\1, \3);/'
Example
$ echo "X.addEventListener(LevelUpEvent.GENERIC_LEVEL_UP, updateLevels);" | sed 's/\(X\).\(addEventListener\)(\(LevelUpEvent.GENERIC_LEVEL_UP, updateLevels\));/EventUtil.\2(\1, \3);/'
EventUtil.addEventListener(X, LevelUpEvent.GENERIC_LEVEL_UP, updateLevels);
Try this
echo "X.addEventListener(LevelUpEvent.GENERIC_LEVEL_UP, updateLevels);" | sed -e "s/\([A-Za-z]\{1,\}\)\.addEventListener(/EventUtil.addEventListener(\1, /"
This regexp will recognize a variable name using
\([A-Za-z]\{1,\}\)
Then .addEventListener(
\.addEventListener(
And replace it with
EventUtil.addEventListener(\1
In which \1 represents the variable name

Find and replace using xargs sed - can I save the results to a file?

My code to replace all instances of 'foo' with 'bar' :
find . -type f |
xargs grep 'foo' -l |
xargs sed -i 's|foo|bar|g'
I'd like to save a list of the modified files to a text document. Is it possible?
EDIT :
This is the final code that worked for me :
find . -type f -print0 |
xargs -0 grep 'foo' -l |
tee result.txt |
xargs -0 sed -i 's|foo|bar|g'
Not sure whether this is the quickest way, but for a few thousand files the difference in speed between this and other suggested methods is probably very small.
Looks like a useless use of xargs, as often in combination with find.
find . -type f -exec grep 'foo' -l {} ";" -exec sed -i 's|foo|bar|g' {} ";" -ls > file.lst
Use it with care, since I didn't test it. I'm not sure, whether you like to change the list of filenames, or the file content. Since you search with grep and sed, I think only working with sed should be sufficient:
find . -type f -exec sed -i 's|foo|bar|g' {} ";" -ls > file.lst