sed search replace pattern - regex

I have files with below text (and more).
import (
"http"
"web"
)
I want to replace all "web" with "pkg/web" (in all files). so the outcome needs to
import (
"http"
"pkg/web"
)
I try sed like
find . -type f -print0 | xargs -0 sed -i '/"web"/c\"pkg/web"'
which gives error.
sed: 1: "test" invalid command code .
what is the correct way?
Thanks.

Problem is that you're using / as regex delimiter but also using / in your replacement string.
Good news is that sed allows different regex delimiters.
This sed with a different regex delimiter should work:
sed -i.bak 's~^\( *\)"web" *$~\1"pkg/web"~g'
UPDATE: To preserve whitespace on LHS of searched string:
find . -type f -print0 | xargs -0 sed -i '' 's~^\([[:space:]]*\)"web"[[:space:]]*$~\1"pkg/web"~g'

find . -type f -print0 | xargs -0 sed -i -e 's#"web"#"pkg/web"#g'
This works fine for me.

Related

Got Error 'repetition-operator operand invalid' with negative look behind regex (?<!(Log\())#"[^"]+"

I want to find all hardcoded strings in my project except words starts with Log(.
Using this regex to do so but getting an error as mentioned above.
KEYWORDS='(?<!(Log\())#"[^"]+"'
find "${SRCROOT}" \( -name "*.h" -or -name "*.m" \) -print0 | xargs -0 egrep --with-filename "($KEYWORDS).*\$
Is there any other alternative regex or script to get the same result.
You might just filter out what you don't want to see:
xargs -0 grep -EH '#"[^"]+"' | grep -v 'LOG\(#"'
If you want to stick with your regular expression:
xargs -0 perl -ne 'print "$ARGV: $_" if /(?<!LOG\()#".+?"/'

Mac: replace text inside files in directory using regular expression

I need to replace all matches (regular expression) in directory from "*::" to be "\*::"
examples: (in multiple php files)
ID::
user::
process::
....
to be:
\ID::
\user::
\process::
I currently use,single commands
find . -type f -name '*.php' -exec sed -i '' s/ID::/\\\\ID::/ {} +
find . -type f -name '*.php' -exec sed -i '' s/user::/\\\\user::/ {} +
find . -type f -name '*.php' -exec sed -i '' s/process::/\\\\process::/ {} +
how to write regular expression to replace any "*::" => "\*::"
thanks,
You want to use "grouping" or "back-referencing" to refer back to a portion of the regular expression. This is done by surrounding the intended group with \( and \), and referring back to them with \1, \2, etc. In your case, the following expression should work:
$ echo -e "ID::\nuser::\nprocess::" | sed 's/\(.*\)::/\\\1::/g'
with the following output:
\ID::
\user::
\process::
I update "bebop" solution to meet my requirements, alot of thanks to him
solution:
sed -i -e 's/\([A-Za-z]*\)::/\\\1::/g' `grep -ril '::' *.php`

sed replace string with string containing dash in all files in folder

In all files in a fodler, I am trying to replace all strings of the type:
load(alpha)
to
load(alpha, lib="lib=~/project-a/alpha")
using sed I tried:
find . -type f -print0 | xargs -0 sed -i 's/load(alpha)/load(alpha, lib="lib=~/project-a/alpha")/g'
But I get the error:
sed: -e expression #1, char 39: unknown option to `s'
Any idea what I am missing?
Thank you!
You get that error because the / delimiters with the substitute command are conflicting with the directory separators in your replacement; after the first directory separator is encountered, sed considers the replacement aborted. Change your delimiter to something else for a more clearer command.
sed -i 's!load(alpha)!load(alpha, lib="lib=~/project-a/alpha")!g'
find . -type f -print0 | xargs -0 sed -i 's/load(alpha)/load(alpha, lib="lib=~\/project-a\/alpha")/g'
In your command the character / is tehe delimiter, so you need to escape any forward-slashes that are part of your data as in /project-a/alpha -> \/project-a\/alpha
Alternatively you can a different delimiter (in this case the # character)
find . -type f -print0 | xargs -0 sed -i 's#load(alpha)#load(alpha, lib="lib=~/project-a/alpha")#g'

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

Using grep to search files provided by find: what is wrong with find . | xargs grep '...'?

When I use the command:
find . | xargs grep '...'
I get the wrong matches. I'm trying to search for the string ... in all files in the current folder.
As Andy White said, you have to use fgrep in order to match for plain ., or escape the dots.
So you have to write (-type f is to only have the files : you obviously don't want the directories.) :
find . -type f | xargs fgrep '...'
or if you still want to use grep :
find . -type f | xargs grep '\.\.\.'
And if you only want the current directory and not its subdirs :
find . -maxdepth 1 -type f | xargs fgrep '...'
'.' matches any character, so you'll be finding all lines that contain 3 or more characters.
You can either escape the dots, like this:
find . | xargs grep '\.\.\.'
Or you can use fgrep, which does a literal match instead of a regex match:
find . | xargs fgrep '...'
(Some versions of grep also accept a -F flag which makes them behave like fgrep.)
#OP, if you are looking for files that contain ...,
grep -R "\.\.\." *
If you're looking for a filename that matches, try:
find . -name "filename pattern"
or
find . | grep "filename pattern"
If your looking for looking for files that match (ie it contains the grep string)
find . | xargs grep "string pattern"
works fine. or simply:
grep "string pattern" -R *
If you are literally typing grep '...' you'll match just about any string. I doubt you're actually typing '...' for your grep command, but if you are, the ... will match any three characters.
Please post more info on what you're searching for, and maybe someone can help you out more.
To complete Jeremy's answer, you may also want to try
find . -type f | xargs grep 'your_pattern'
or
find . -type f -exec grep 'your_pattern' {} +
Which is similar to a xargs
I might add : RTFM ! Or in a more polite way : use & abuse of
man command
!