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
Related
I'm doing an in-place search & replace with Perl. I need to replace all words in all lines that contain another word. For instance, remove all const only in lines containing PMPI_. With sed I can do:
sed -i "/PMPI_/ s/const//g" file.c
However I need multi-line capabilities and sed doesn't seem to be the right tool for the job. I'm using Perl for everything else anyway. I tried
perl -pi -e "/PMPI_/ s/const//g" file.c
And other variations with no success. I could only find vim regex equivalents searching this site.
The syntax is:
perl -pi -e "s/const//g if /PMPI_/" file
Note: you say you need multiline capabilities. I don't think you are looking for the slurp mode (that loads the whole file), but you could also work by paragraphs with the -00 option:
echo 'PMPI_ const
const const' | perl -00 -p -e "s/const//g if /PMPI_/"
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]/.
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
I want to replace (whole string)
$(TOPDIR)/$(OSSCHEMASDIRNAME)
with
/udir/makesh/$(OSSCHEMASDIRNAME)
in a makefile
I tried with
perl -pi.bak -e "s/\$\(TOPDIR\)\/\$\(OSSCHEMASDIRNAME\)/\/udir\/makesh\/\$\(OSSCHEMASDIRNAME\)/g " makefile
but i am getting unmatched parentheses error
You have to "double" escape the dollar sign. Like this:
echo "\$(TOPDIR)/\$(OSSCHEMASDIRNAME)" | perl -p -e "s/\\$\(TOPDIR\)\/\\$\(OSSCHEMASDIRNAME\)/\/udir\/makesh\/\\$\(OSSCHEMASDIRNAME\)/g"
First off, you don't need to use / for regular expressions. They're just canonical. You can use pretty much anything. Thus your code can become (simplify away some \):
perl -pi.bak -e "s|\$\(TOPDIR\)/\$\(OSSCHEMASDIRNAME\)|/udir/makesh/\$\(OSSCHEMASDIRNAME\)|g " makefile
Now to actually address your issue, because you're using " instead of ', the shell attempts to figure out what $\ means which is then replaced with (presumably) nothing. So what you really want is:
perl -p -i.bak -e 's|\$\(TOPDIR\)/\$\(OSSCHEMASDIRNAME\)|/udir/makesh/\$\(OSSCHEMASDIRNAME\)|g' makefile
When in doubt about escaping, you can simply use quotemeta or \Q ... \E.
perl -pe 's#\Q$(TOPDIR)\E(?=/\Q$(OSSCHEMASDIRNAME)\E)#/udir/makesh#;'
Note the use of a look-ahead assertion to save us the trouble of repeating the trailing part in the substitution.
A quotemeta solution would be something like:
perl -pe 'BEGIN { $dir = quotemeta(q#$(TOPDIR)/$(OSSCHEMASDIRNAME)#); }
s#$dir#/udir/makesh/$(OSSCHEMASDIRNAME)#;'
Of course, you don't need to use an actual one-liner. When the shell quoting is causing troubles, the simplest option of them all is to write a small source file for your script:
s#\Q$(TOPDIR)\E(?=/\Q$(OSSCHEMASDIRNAME)\E)#/udir/makesh#;
And run with:
perl -p source.pl inputfile
Apologies for the simple question. I don't clean text or use regex often.
I have a large number of text files in which I want to remove every line until my regex finds a match. There's usually about 15 lines of fluff before I find a match. I was hoping for a perl one-liner that would look like this:
perl -p -i -e "s/.*By.unanimous.vote//g" *.txt
But this doesn't work.
Thanks
Solution using the flip-flop operator:
perl -pi -e '$_="" unless /By.unanimous.vote/ .. 1' input-files
Shorter solution that also uses the x=!! pseudo operator:
per -pi -e '$_ x=!! (/By.unanimous.vote/ .. 1)' input-files
Have a try with:
If you want to get rid until the last By.unanimous.vote
perl -00 -pe "s/.*By.unanimous.vote//s" inputfile > outputfile
If you want to get rid until the first By.unanimous.vote
perl -00 -pe "s/.*?By.unanimous.vote//s" inputfile > outputfile
Try something like:
perl -pi -e "$a=1 if !$a && /By\.unanimous\.vote/i; s/.*//s if !$a" *.txt
Should remove the lines before the matched line. If you want to remove the matching line also you can do something like:
perl -pi -e "$a=1 if !$a && s/.*By\.unanimous\.vote.*//is; s/.*//s if !$a" *.txt
Shorter versions:
perl -pi -e "$a++if/By\.unanimous\.vote/i;$a||s/.*//s" *.txt
perl -pi -e "$a++if s/.*By\.unanimous\.vote.*//si;$a||s/.*//s" *.txt
You haven't said whether you want to keep the By.unanimous.vote part, but it sounds to me like you want:
s/[\s\S]*?(?=By\.unanimous\.vote)//
Note the missing g flag and the lazy *? quantifier, because you want to stop matching once you hit that string. This should preserve By.unanimous.vote and everything after it. The [\s\S] matches newlines. In Perl, you can also do this with:
s/.*?(?=By\.unanimous\.vote)//s
Solution using awk
awk '/.*By.unanimous.vote/{a=1} a==1{print}' input > output