Grep to find a pattern and replace in same line - unix

I have a project directory with folders containing .html files. I want to find those files which have the pattern -
'btn-primary.*{.*Save'
And replace the
'btn-primary' word with 'btn-primary Save'
only in those lines.
What I have done:
grep -rl -e 'btn-primary.*{Save' . |xargs sed -i 's/btn-primary/btn-primary Save/g'
What this did:
This found all files that have that pattern, that's okay. Then, sed ran on all of those files and replaced 'btn-primary' with 'btn-primary save' wherever it got - which is not what I want
What I want: to replace on those lines where there is 'Save' somewhere after 'btn-primary'.
Any help will be very much appreciated.
Regards,
Rahul

Why are you using grep at all? Sed does pattern matching:
sed -e 's/btn-primary\(.*{.*Save\)/btn-primary Save\1/g'
or:
sed -e 's/\(btn-primary\)\(.*{.*Save\)/\1 Save\2/g'
If you are using grep to try to trim down the number of files that sed will operate on, you're fooling yourself if you believe that is more efficient. By doing that, you will read every file that doesn't match only once, but every file that does match will be read twice. If you only use sed, every file will be read only once.

Related

Sed command matching pattern UNIX

I want to delete lines from the file using sed command in linux but problem is that
if , I want to match "abcd" it matches "abcd.efgh" also . I just want to match not "abcd.efgh"
. I have searched on google but didnt find any solution .
With awk you can do:
awk '/abcd/ && !/abcd\.efgh/' file
It will match lines that are abcd but not abcd.efgh
Perhaps this is simply what you want:
sed -i '/^abcd$/d' file
It would only delete lines that give an exact match of it.
perl -lne 'print if(/\babcd\b/)' your_file
This might work for you (GUN sed):
sed '/abcd\.efgh/b;/abcd/d' file
or to put another way:
sed '/abcd/{/abcd\.efgh/!d}' file

To replace a set of strings in a file with another string in a unix file

I have a parameter name like
PAR="DBS_OUT"
and I have a text file(Repla.txt) with below values:
DB_TECH
DB_ADMIN
DB_TERA
DB_APS
These values in the files can defer but the parameter value will remain the same.
Now I have some Unix shell script where I need to find all such values mentioned in the file (Repla.txt)
and replace them with the parameter (PAR). Since the values in the Repla.txt is not fixed I am not able to use the sed command. for eg:
sed 's/old/new/g' input.txt > output.txt
Can anyone please help me.
Thanks
I'm not sure I completely understand what you are trying to do but if you are trying to use the values contained in Repla.txt as the strings that you want to replace in other files then the following bash line will do what you want:
PAR="DBS_OUT"; for FIND in `cat Repla.txt`; do $( find /path/to/files -name 'test?.txt' -exec sed -i "s/$FIND/$PAR/g" '{}' \;); done;
It will replace the strings contained in Repla.txt with the string DBS_OUT in all files that match test?.txt in the dir (and subdirs) /path/to/files. You will need to understand how find works.
Also note that I am not telling sed to backup, you probably want to test this out on some test files before you execute it for real. Hopefully you also have your scripts in source control so its not a big deal if you mess things up.
I hope your replacement on Capital letters only.
sed 's/DBS_[A-Z]*/DBS_OUT/g' repla.txt > destination file
or
sed 's/DBS_[A-Z]*/DBS_OUT/g' repla.txt

Delete all contents of the file using sed

I want to empty a file using sed command. I searched lot of forums and tutorial. There is no available to delete all contents of the file. How to delete all contents of the file using sed command.
It looks like a strange request. Anyway, this is a way:
sed -i '/^/d' file
sed -i does an in-place replacement.
/^/ matches lines, in this case all of them because ^ means "beginning of line".
/d deletes them.
Or shorter (thanks glenn jackman as always):
sed -i d file
You don't need sed for this. To empty a file:
> filename
with no command, that redirection will truncate the file.
Try this sed. It will remove all.
sed -ni '' file
n do not print if not told to do so.
i in place.
Since no code is given, file will be replaced by nothing.

sed -i option is not working on solaris

I am using sed to replace a line with NULL in a file. The command i used is
sed -i "s/.*shayam.*//g" FILE
This is working fine in linux. shayam is replaced with blank in the FILE. But when i used this in solaris it is showing some error.
sed: illegal option -- i
How to use -i functionality of sed in solaris. Kindly help.
The -i option is GNU-specific. The Solaris version does not support the option.
You will need to install the GNU version, or rename the new file over the old one:
sed 's/.shayam.//g' FILE > FILE.new && mv FILE.new FILE
I just answered a similar question sed -i + what the same option in SOLARIS, but for those who find this thread instead (I saw it in the related thread section):
The main problem I see with most answers given is that it doesn't work if you want to modify multiple files. The answer I gave in the other thread:
It isn't exactly the same as sed -i, but i had a similar issue. You
can do this using perl:
perl -pi -e 's/find/replace/g' file
doing the copy/move only works for single files. if you want to
replace some text across every file in a directory and
sub-directories, you need something which does it in place. you can do
this with perl and find:
find . -exec perl -pi -e 's/find/replace/g' '{}' \;
sed doesn't haven an -i option.
You are probably using some vendor-specific variant of sed. If you want to use the vendor-specific non-standardized extensions of your vendor-specific non-standardized variant of sed, you need to make sure that you install said vendor-specific non-standardized variant and need to make sure that you call it and don't call the standards-compliant version of sed that is part of your operating environment.
Note that as always when using non-standardized vendor-specific extensions, there is absolutely no guarantee that your code will be portable, which is exactly the problem you are seeing.
In this particular case, however, there is a much better solution: use the right tool for the job. sed is a stream editor (that's why it is called "sed"), i.e. it is for editing streams, not files. If you want to edit files, use a file editor, such as ed:
ed FILE <<-HERE
,s/.shayam.//g
w
q
HERE
See also:
Unable to use SED to edit files fast
How can I replace a specific line by line number in a text file?
Either cat the file or try <?
Then pipe (|) the result to a temp file and if all goes well (&&) mv the tempfile to the original file.
Example:
cat my_file | sed '!A!B!' > my_temp_file && mv my_temp_file my_file

How to sed search and replace without changing ownership

I found this command line search and replace example:
find . -type f -print0 | xargs -0 sed -i 's/find/replace/g'
It worked fine except it changed the date and file ownership on EVERY file it searched through, even those that did not contain the search text.
What's a better solution to this task?
Using the -c option (if you are on Linux) ought to cause sed to preserve ownership. As you are using the command, it is in fact rewriting every file, even though it is not making changes to the files that do not contain find.
The easiest way to fix that would be to only execute sed on the files if the contain the text by using grep first:
find . -type f | while read file; do
grep -q find $file && sed -i 's/find/replace/g' $file
done
This does require reading each file twice (in the worst case), so it might be a little slower. Hopefully, though, your OS should keep the file in its disk cache, so you shouldn't see much of a slowdown, since this process is definitely I/O-bound, not CPU-bound.
Some distro's versions of sed (namely, RedHat and family) have added a -c option that accomplishes this, in which case see #Isaac's answer.
But for those with an unpatched GNU sed, the easiest way I've found is to simply substitute with perl, which rewrites files similar to sed -c when available. The following commands are basically equivalent:
sed -ci 's/find/replace/'
perl -pi -e 's/find/replace/'
Just don't get too excited and do perl -pie; like with sed -ie, instead of interpreting as another option, it will use e as an argument to -i, and use it as a suffix to backup the original file. See perldoc perlrun for more details there.
Perl's regex parsing is a little different from sed (better, imo) for more complicated things: generally speaking, use less backslashes.

Resources