In file.txt I have a line like this:
^/string string_to_be_replaced
that must become:
^/string replaced_string
So I created a perl script:
perl -pi -e "s[\^/string$(.*)$] [\^/string$(.*) replaced_string]" /file.txt
But the problem is that perl doesn't find the line starting with ^/string
perl -pi -e "s[\^/string .+$][^/string replaced_string]" /file.txt
or
perl -pi -e "s[\^/string \K.+$][replaced_string]" /file.txt
The first portion of your regex, [\^/string$(.)$], looks for a line containing "^/string", followed by an end-of-line, followed by a single character (which is captured), and finally another end-of-line. Since the file is processed line-by-line (looking at only one line at a time), a pattern containing two end-of-lines can never match.
You probably want:
s[\^/string string_to_be_replaced][^/string replaced_string]
assuming that you have only a single string_to_be_replaced and only want to replace it when it's preceded by string. If not, then more details would be useful.
Related
I am trying to add 5 blank line spaces in a text file (text.txt) before and after string pattern matches. I used the following to get spaces after the 'string' match which worked for me-
sed '/string/{G;G;G;G;G;}' text.txt
I want to apply the same sed command to obtain 5 blank lines before the 'string' Here I don't want spaces, but rather blank lines before and after them. Any suggestions?
sed -r 's/(^.*)(string)(.*$)/\1\n\n\n\n\n\2\n\n\n\n\n\3/' text.txt
Use -r or -E to allow regular expressions, split likes into three sections and then substitute the line for the first section, 5 new lines, the second section, 5 new lines and then finally the third section.
Use this Perl one-liner:
perl -pe 's/string/\n\n\n\n\n$&\n\n\n\n\n/' text.txt
The Perl one-liner uses these command line flags:
-e : Tells Perl to look for code in-line, instead of in a file.
-p : Loop over the input one line at a time, assigning it to $_ by default. Add print $_ after each loop iteration.
s/PATTERN/REPLACEMENT/ : change PATTERN to REPLACEMENT.
$& : matched pattern.
\n : newline character.
SEE ALSO:
perldoc perlrun: how to execute the Perl interpreter: command line switches
perldoc perlrequick: Perl regular expressions quick start
For a single string match:
$ sed -e '/string/{ s/^/\n\n\n\n\n/; s/$/\n\n\n\n\n/ }' text.txt
For multiple strings, assuming same requirements:
$ sed -E '/(string1|string2|string3)/{ s/^/\n\n\n\n\n/; s/$/\n\n\n\n\n/ }' text.txt
This might work for you:
sed '/string/{G;s/\(string\)\(.*\)\(.\)/\3\3\3\3\3\1\3\3\3\3\3\2/}' file
Match on string, append an empty line, pattern match using the newline to separate the match by 5 lines either side.
And an awk version:
awk '{if(/string1|string2|.../){printf "\n\n\n\n\n%s\n\n\n\n\n",$0}else{print}}' file
I want to do search and replace(foo to foobar) with bash using perl command:
sudo perl -0777 -i -pe s/'foo'/'foobar'/gs a.txt
but I don't always know what is 'foo', so I want a variable kind of thing which stores the matched pattern.
Also can I get a substring of the matched pattern? Like 'foo' is replaced with 'oobar'(foo becomes oo)?
Use the expression evaluation modifier e.
perl -0777 -i -pe's/(foo)/substr($1, 1) . "bar"/egs' a.txt
$& refers to the entire matched pattern and instead of taking substring of that I used negative lookbehind (?<!u) this means any character other than u:
sudo perl -i -0777 -pe s/(?<!u)'oo'/'u$&'/gs
This will match not only any foo but any occurrence of oo but never uoo and replace it with uoobar.
In the example you gave, you don't need to use the matched text.
perl -pe's/foo\K/bar/g'
In the scenario you described, you don't need to use the matched text.
perl -pe's/f\Koo/oobar/g'
That said, $& contains the matched text.
perl -pe's/foo/$&bar/g'
And $1 contains the text matched by the earliest capture, $2 contains the text matched by the second earliest capture, etc.
perl -pe's/(f)oo/$1oobar/g'
And /e can be used to treat the replacement expression as code to execute for each match.
perl -pe's/foo/ substr($&,0,1)."oobar" /eg'
There's no point in using /s since the pattern doesn't contain ..
There's no point in using -0777 since your pattern can't span lines.
The quotes you used were useless, and it's less noisy to quote the entire program instead of individual sections of it.
I need to replace a particular range of characters in each line of a file.
I tried this
perl -i -pe 'r77,79c/XXX/g' file
I am trying to change the 77th to 79th characters to XXX using Perl, but above code is not working.
you want to replace chars at position [77-79] with XXX?
try
perl -i -piorig_* -e "substr($_,76,3)=XXX" file
a backup file called orig_file will be created cause of preventing possible dataloss..
perl -i -pe 's/.{76}\K.../XXX/' file
You wrote:
Actually i want to search a pattern in a file and whatever lines matching that pattern needs to be replaced to 50th & 51st character to XX
Using sed:
sed -r '/pattern/s/^(.{49})..(.*)$/\1XX\2/' file
sed "/pattern/ s/^\(.\{49\}\)../\1XX/" YourFile
we don't touch the end
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
I use perl to check some text input for a regex pattern, but one pattern doesn't work with perl -pe.
Following pattern doesn't work with the command call:
s![a-zA-Z]+ +(?:.*?)/(?:.*)Comp-(.*)/.*!$1!
I use the linux shell. Following call I use to test my regex:
cat test | perl -pe 's![a-zA-Z]+ +(?:.*?)/(?:.*)Comp-(.*)/.*!$1!'
File test:
A MaintanceGie?\195?\159mannFlock/System/Comp-Database.cpp
A MaintanceGie?\195?\159mannFlock/System/Comp-Cache/abc.h
Result:
A MaintanceGie?\195?\159mannFlock/System/Comp-Database.cpp
Cache
How can I remove the first result?
Thanks for any advice.
That last slash after "Comp-(.*)" may be what's doing it. Your file content in the "Database" doesn't have a slash. Try replacing Comp-(.*)/.* with Comp-(.*)[/.].* so you can match either the subdirectory or the file extension.
$ cat input
A MaintanceGie?\195?\159mannFlock/System/Comp-Database.cpp
A MaintanceGie?\195?\159mannFlock/System/Comp-Cache/abc.h
$ perl -ne 'print if s![a-zA-Z]+ +(?:.*?)/(?:.*)Comp-(.*)/.*!$1!' input
Cache
The problem is in last slash character in the regex. Instead of escaping the dot, it is just normal slash character, which is missing from input string. Try this:
s![a-zA-Z]+ +(?:.*?)/(?:.*)Comp-(.*)[./].*!$1!
Edit: Updated to match new input data and added another option:
On the other hand, your replacement regex might be replaced by something like:
perl -ne 'print "$1\n" if /Comp-(.*?)[.\/]/'
Then there is no need to parse full line with whatever it contains.
\s match whitespace (spaces, tabs, and line breaks) and '+' means one or more characters. In this case '\s+' would mean search for one or more whitespaces.
cat test
A MaintanceGie?\195?\159mannFlock/System/Comp-Database.cpp
A MaintanceGie?\195?\159mannFlock/System/Comp-Cache/abc.h
perl -ne 'print "$1\n" if /\w+?\d+?\d+\w+\/\w+\/Comp-(\w+)[\/]/' test