So I looked around on Stackoverflow and I understand finding and replacing text works something like this:
perl -pi -w -e 's/www.example.com/www.pressbin.com/g;' *.html
However, what if the text I want to find and replace is a filepath that has slashes? How do I do it then?
perl -pi -w -e 's/path/to/file/new/path/to/file/g;' *.html
With perl regexes, you can use any character except spaces as regex delimiter, although
Characters in \w (so s xfooxbarx is the same as s/foo/bar/) and
Question marks ? (implicitly activates match-only-once behaviour, deprecated) and
single quotes '...' (turns of variable interpolation)
should be avoided. I prefer curly braces:
perl -pi -w -e 's{path/to/file}{new/path/to/file}g;' *.html
The delimiting character may not occur inside the respective strings, except when they are balanced braces or properly escaped. So you could also say
perl -pi -w -e 's/path\/to\/file/new\/path\/to\/file/g;' *.html
but that is dowrnright ugly.
When using braces/parens etc there can be whitespace between the regex and the replacement, allowing for beatiful code like
$string =~ s {foo}
{bar}g;
Another interesting regex option in this context is the quotemeta function. If your search expression contains many characters that would usually be interpreted with a special meaning, we can enclose that string inside \Q...\E. So
m{\Qx*+\E}
matches the exact string x*+, even if characters like *, '+' or | etc. are included.
You can use other characters than '/' to specify patterns. For example:
perl -pi -w -e 's,path/to/file,new/path/to/file,g;' *.html
perl -pi -w -e 's/path\/to\/file/new\/path\/to\/file/g;' *.html
Related
I have this regex: 'src=\d' which match all src attributes who start with a number in a file. I need to store it within a variable, cut src= out and write from there a new $string with \d concatenated to it: $string . $d. Is it possible to store only \d in a variable with a single command line? How to use cut and variable in a command line with perl? Is it possible?
perl -pi -w -e 's/src="\d+/src="http:\/\/website.com\/\d+/g’ file.tsv
I'm not exactly sure what you mean, but I think you want something like this, where the () brackets store the number and the $1 replaces it back.
perl -pi -w -e 's/src="(\d+)/src="http:\/\/website.com\/$1/g’ file.tsv
And you can avoid the so-called 'leaning toothpick syndrome by selecting a different delimiter for the s/// operation like s{}{}
perl -pi -w -e 's{src="(\d+)}{src="http://website.com/$1}g’ file.tsv
I have a list of lines:
<some_random_text="someval" my_val_="0.4" some_random_text_1="someval_">
<some_random_text="someval" my_val_="0.8" some_random_text_1="someval_">
<some_random_text="someval" my_val_="1.2" some_random_text_1="someval_">
and so on.
From each line, I want to return the numeric value given after my_val_. How can I do this in bash?
Within this very rigid structure, what you want to do is quite easy using sed:
sed 's/.*my_val_="\([0-9.]\{1,\}\)".*/\1/' file
or using extended regular expressions:
sed -r 's/.*my_val_="([0-9.]+)".*/\1/' file
This captures the part you're interested in (the digits and dots between the quotes) and uses them to replace the contents of the line.
As mentioned in the comments (thanks), the switch to enable extended regular expressions differs between versions of sed. Out of habit, I tend to use -r but some implementations (such as BSD sed on OSX) work with -E instead. Others work with either -r or -E but neither option is defined by the standard.
This could also be done in native bash (although I wouldn't recommend it...):
re='my_val_="([0-9.]+)"'
while read -r line; do
[[ $line =~ $re ]] && echo "${BASH_REMATCH[1]}"
done < file
=~ is the regex match operator. The captured digits and dots are stored in element 1 of the special array BASH_REMATCH.
The sed and bash approaches are subtly different, as the sed version will print all lines in the file, even if they don't match the pattern. If this is a problem, you can add the -n switch and a p at the end of the command to print matching lines:
sed -nr 's/.*my_val_="([0-9.]+)".*/\1/p' file
With grep:
grep -oP 'my_val_="\K[^"]*' filename
-o so that grep only prints only the match, -P so that Perl-compatible regexes are used.
The \K in the regex removes from the match everything that was matched by the part of the regex that came before it; this has the effect of a lookbehind: only non-quote characters that come directly after my_val_=" are matched.
I use this classic perl one liner to replace strings in multiple files recursively
perl -pi -e 's/oldstring/newstring/g' `grep -irl oldstring *`
But this has failed me as I want to find the string:
'$user->primaryorganisation->id'
and replace with
$user->primaryorganisation->id
I can't seem to escape the string correctly for the line to run successfully.
Any help gratefully received!
Try this one. Lots of escapes. Go with TLPs suggestion and use a source file.
perl -pi -e "s/'\\\$user->primaryorganisation->id'/\\\$user->primaryorganisation->id/g" `grep -irl "'\$user->primaryorganisation->id'" *`
Explanation:
three backslashes: the first two tell the shell to produce a literal backslash; the thrid one escapes the $ for the shell; that makes \$ for Perl, which needs the backslash to escape the variable interpolation
double quotes " to put single quotes ' inside them
one backslash and a dollar \$ for grep so the shell passes on a literal dollar sign
When you want to represent a single quote in a perl but can't because the one-liner uses single quotes itself, you can use \047, the octal code for single quote. So, this should work:
s/\047(\$user->primaryorganisation->id)\047/$1/g
I recommend Minimal Perl by Maher for more-than-you-wanted-to-know about the art of one-lining perl.
To produce
...'...
you can generically use
'...'\''...'
As such,
s/'(\$user->primaryorganisation->id)'/$1/g
becomes
's/'\''(\$user->primaryorganisation->id)'\''/$1/g'
so
find -type f \
-exec perl -i -pe's/'\''(\$user->primaryorganisation->id)'\''/$1/g' {} +
I wanted to replace /**/ across all files in a folder. I tried:
perl -pi -w -e 's/\/**\///g;' *.java
But got an error: Nested quantifiers in regex; marked by <-- HERE in m//** <-- HERE // at -e line 1.
Same thing with:
sed 's/\/**\///g;'
I need to basically replace /**/ with an empty space.
You need to escape the asterisks as well. To preserve readability, you may want to use other delimiters as well:
sed "s#/\*\*/##g"
You can specify * within []:
perl -pi -w -e 's#/[*]{2}/# #g;' *.java
Alternatively, you can make use of quotemeta operator:
perl -pi -w -e 's#\Q/**/\Q# #g;' *.java
which escapes all ASCII characters not matching /[A-Za-z_0-9]/.
how to replace a String inside a File using perl ?
perl -pi -e 's/Arun/Brun/g' *
this worked fine for me
but when i tried to change class/students/a to class1/students1/B it throws error how to solve this problem ..i tried adding back slash (\) before every (/) but it didn't help
perl -pi -e 's/class/students/a/class1/students1/B/g' *
You are using / as regex delimiter.There are / even in your pattern and replacement. You need to somehow ensure that these / should not be treated as delimiter.
You have two options:
Escape the / in your pattern and replacement as:
perl -pi -e 's/class\/students\/a/class1\/students1\/B/g' *
Or use a different delimiter:
perl -pi -e 's#class/students/a#class1/students1/B#g' *
Method 2 is preferred as it keeps your regex short and clean.
Try perl -pi -e 's{class/students/a}{class1/students1/B}g' *
From perldoc perlop:
Any non-whitespace delimiter may
replace the slashes. Add space after
the s when using a character allowed
in identifiers. (...) If the
PATTERN is delimited by bracketing
quotes, the REPLACEMENT has its own
pair of quotes, which may or may not
be bracketing quotes, e.g.,
s(foo)(bar) or s/bar/.
Thank you perldoc perlop:
My problem is changin Oracle Home has solve by your command. one more trick I have done to replace with shell variable.
export ORACLE_HOME=/oracle/product/11.2.0.3/db_1
perl -pi -e 's{REPLACEWITHORACLEHOME}{'$ORACLE_HOME'}g' filename
more scripted way is :
for y in `ls`;do perl -pi -e 's{REPLACEWITHORACLEHOME}{'$ORACLE_HOME'}g' $y;done