Shell script to replace string dynamically - linux

I am writing a shell script for linux which takes argument as port no.
inside file following is a line which needs to be updated:
define('NO_OF_PORTS',10);
I need to replace that 10 by the argument passed.
But this should be dynamic, like next time I pass new port no it must get updated.

Using sed:
s="define('NO_OF_PORTS',10);"
n=25
sed "s/\('NO_OF_PORTS',\)[0-9]*/\1$n/" <<< "$s"
define('NO_OF_PORTS',25);
To change inline in the file use:
sed -i.bak "s/\('NO_OF_PORTS',\)[0-9]*/\1$n/" file

You can use sed in the script to edit the file
sed -i s/NO_OF_PORTS\',[0-9]*/NO_OF_PORTS\',$1/ $2

1.txt has
define('NO_OF_PORTS',19)
shell script
#!/bin/sh
echo $1
sed -i -r '/NO_OF_PORTS/ s/'[0-9]+'/'$1'/g' 1.txt
run
linux:/home/test # ./replace_port.sh 78
linux:/home/test # cat 1.txt
define('NO_OF_PORTS',78)

Related

How to apply my sed command to some lines of all my files?

I've 95 files that looks like :
2019-10-29-18-00/dev/xx;512.00;0.4;/var/x/xx/xxx
2019-10-29-18-00/dev/xx;512.00;0.68;/xx
2019-10-29-18-00/dev/xx;512.00;1.84;/xx/xx/xx
2019-10-29-18-00/dev/xx;512.00;80.08;/opt/xx/x
2019-10-29-18-00/dev/xx;20480.00;83.44;/var/x/x
2019-10-29-18-00/dev/xx;3584.00;840.43;/var/xx/x
2019-10-30-00-00/dev/xx;2048.00;411.59;/
2019-10-30-00-00/dev/xx;7168.00;6168.09;/usr
2019-10-30-00-00/dev/xx;3072.00;1036.1;/var
2019-10-30-00-00/dev/xx;5120.00;348.72;/tmp
2019-10-30-00-00/dev/xx;20480.00;2033.19;/home
2019-10-30-12-00;/dev/xx;5120.00;348.72;/tmp
2019-10-30-12-00;/dev/hd1;20480.00;2037.62;/home
2019-10-30-12-00;/dev/xx;512.00;0.43;/xx
2019-10-30-12-00;/dev/xx;3584.00;794.39;/xx
2019-10-30-12-00;/dev/xx;512.00;0.4;/var/xx/xx/xx
2019-10-30-12-00;/dev/xx;512.00;0.68;/xx
2019-10-30-12-00;/dev/xx;512.00;1.84;/var/xx/xx
2019-10-30-12-00;/dev/xx;512.00;80.08;/opt/xx/x
2019-10-30-12-00;/dev/xx;20480.00;83.44;/var/xx/xx
2019-10-30-12-00;/dev/x;3584.00;840.43;/var/xx/xx
For some lines I've 2019-10-29-18-00/dev and for some other lines, I've 2019-10-30-12-00;/dev/
I want to add the ; before the /dev/ where it is missing, so for that I use this sed command :
sed 's/\/dev/\;\/dev/'
But How I can apply this command for each lines where the ; is missing ? I try this :
for i in $(cat /home/xxx/xxx/xxx/*.txt | grep -e "00/dev/")
do
sed 's/\/dev/\;\/dev/' $i > $i
done
But it doesn't work... Can you help me ?
Could you please try following with GNU awkif you are ok with it.
awk -i inplace '/00\/dev\//{gsub(/00\/dev\//,"/00;/dev/")} 1' *.txt
sed solution: Tested with GNU sed for few files and it worked fine.
sed -i.bak '/00\/dev/s/00\/dev/00\;\/dev/g' *.txt
This might work for you (GNU sed & parallel):
parallel -q sed -i 's#;*/dev#;/dev#' ::: *.txt
or if you prefer:
sed -i 's#;*/dev#;/dev#' *.txt
Ignore lines with ;/dev.
sed '/;\/dev/{p;d}; s^/dev^;/dev^'
The /;\/dev/ check if the line has ;/dev. If it has ;/dev do: p - print the current line and d - start from the beginning.
You can use any character with s command in sed. Also, there is no need in escaping \;, just ;.
How I can apply this command for each lines where the ; is missing ? I try this
Don't edit the same file redirecting to the same file $i > $i. Think about it. How can you re-write and read from the same file at the same time? You can't, the resulting file will be in most cases empty, as the > $i will "execute" first making the file empty, then sed $i will start running and it will read an empty file. Use a temporary file sed ... "$i" > temp.txt; mv temp.txt "$i" or use gnu extension -i sed option to edit in place.
What you want to do really is:
grep -l '00/dev/' /home/xxx/xxx/xxx/*.txt |
xargs -n1 sed -i '/;\/dev/{p;d}; s^/dev^;/dev^'
grep -l prints list of files that match the pattern, then xargs for each single one -n1 of the files executes sed which -i edits files in place.
grep for filtering can be eliminated in your case, we can accomplish the task with a single sed command:
for f in $(cat /home/xxx/xxx/xxx/*.txt)
do
[[ -f "$f" ]] && sed -Ei '/00\/dev/ s/([^;])(\/dev)/\1;\2/' "$f"
done
The easiest way would be to adjust your regex so that it's looking a bit wider than '/dev/', e.g.
sed -i -E 's|([0-9])/dev|\1;/dev|'
(note that I'm taking advantage of sed's flexible approach to delimiters on substitute. Also, -E changes the group syntax)
Alternatively, sed lets you filter which lines it handles:
sed -i '/[0-9]\/dev/ s/\/dev/;/dev/'
This uses the same substitution you already have but only applied on lines that match the filter regex

How to replace string into numbers using sed?

I am trying to replace string into number from the file
So, I have variable &FLOW which need to change to 001, ex :
cat file.txt
This is file ' PISP &FLOW'
PISD.DATA.CYCLE&FLOW..ONE
desired output
This is file ' PISP 001'
PISD.DATA.CYCLE001.ONE
I tried below commands in a script :
for item in file.txt
do
sed 's/\&FLOW/\./001/g' $item
sed 's/\&FLOW/001/g' $item
done
It is giving error. The second sed command is working, but I need to run first the beginning sed command otherwise after running first the second sed command, it would ignore the beginning sed command.
Any help would be appreciated!
Use a single sed command and use -i to actually modify the file contents and you need to pass file.txt as the input for the sed command:
sed -i 's/&FLOW\.\{0,1\}/001/g' file.txt
See the online demo. If you are using it in Mac OS, you need sed -i '' 's/&FLOW\.\{0,1\}/001/g' file.txt. Also see sed edit file in place.
Pattern details
It is a POSIX BRE compliant pattern matching
&FLOW - a literal &FLOW substring
\.\{0,1\} - 0 or 1 occurrence of a . char.
try this:
for item in file.txt
do
sed 's/\&FLOW\./001/g' $item
sed 's/\&FLOW/001/g' $item
done
You had a redundant / in after FLOW
This might also work:
sed -i 's/\&FLOW[\.]?/001/g' file.txt

Linux command to replace set of lines for a group of files under a directory

I need to replace first 4 header lines of only selected 250 erlang files (with extension .erl), but there are 400 erlang files in total in the directory+subdirectories, I need to avoid modifying the files which doesn't need the change.
I've the list of file names that are to be modified, but don't know how to make my linux command to make use of them.
sed -i '1s#.*#%% This Source Code Form is subject to the terms of the Mozilla Public#' *.erl
sed -i '2s#.*#%% License, v. 2.0. If a copy of the MPL was not distributed with this file,#' *.erl
sed -i '3s#.*#%% You can obtain one at http://mozilla.org/MPL/2.0/.#' *.erl
sed -i '4s#.*##' *.erl
in the above commands instead of passing *.erl I want to pass those list of file names which I need to modify, doing that one by one will take me more than 3 days to complete it.
Is there any way to do this?
Iterate over the shortlisted file names using awk and use xargs to execute the sed. You can execute multiple sed commands to a file using -e option.
awk '{print $1}' your_shortlisted_file_lists | xargs sed -i -e first_sed -e second_sed $1
xargs gets the file name from awk in a $1 variable.
Try this:
< file_list.txt xargs -1 sed -i -e 'first_cmd' -e 'second_cmd' ...
Not answering your question but a suggestion for improvement. Four sed commands for replacing header is inefficient. I would instead write the new header into a file and do the following
sed -i -e '1,3d' -e '4{r header' -e 'd}' file
will replace the first four lines of the file with header.
Another concern with your current s### approach is you have to watch for special chars \, & and your delimiter # in the text you are replacing.
You can apply the sed c (for change) command to each file of your list :
while read file; do
sed -i '1,4 c\
%% This Source Code Form is subject to the terms of the Mozilla Public\
%% License, v. 2.0. If a copy of the MPL was not distributed with this file,\
%% You can obtain one at http://mozilla.org/MPL/2.0/.\
' "$file"
done < filelist
Let's say you have a file called file_list.txt with all file names as content:
file1.txt
file2.txt
file3.txt
file4.txt
You can simply read all lines into a variable (here: files) and then iterate through each one:
files=`cat file_list.txt`
for file in $files; do
echo "do something with $file"
done

How to delete lines from file with sed\awk?

I have file, with lines, contains ip with netmask
a.b.c.d/24
w.x.y.z/32
etc
How to delete delete specific row?
i'm using
sed -ie "s#a.b.c.d/24##g" %filname%
but after the removal is an empty string in file.
It should run inside a script, with ip as parameter and also work in freebsd under sh.
Sed solution
sed -i '/<pattern-to-match-with-proper-escape>/d' data.txt
-i option will change the original file.
Awk solution
awk '!/<pattern-to-match-with-proper-escape>/' data.txt
Using sed:
sed -i '\|a.b.c.d/24|d' file
Command line arg:
For the input being command line argument, say 1st argument($1):
sed -i "\|$1|d" file
Replace $1 with appropriate argument number as is your case.
You should use d (delete) not g. Also do not use s (replacement).
sed -ie '/a.b.c.d\/24/d' %filename%
In a script you should using it in this way
IP=$1
IPA=${IP////\\/}
sed -i /"${IPA}"/d %filename%
And the script parameter should be called in this way:
./script.sh a.b.c.d/24
perl -i -lne 'print unless(/a.b.c.d\/24/)' your_file
or in awk if you donot want to do inplace editing:
awk '$0!~/a.b.c.d\/24/' your_file

Find and replace in shell scripting

Is it possible to search in a file using shell and then replace a value? When I install a service I would like to be able to search out a variable in a config file and then replace/insert my own settings in that value.
Sure, you can do this using sed or awk. sed example:
sed -i 's/Andrew/James/g' /home/oleksandr/names.txt
You can use sed to perform search/replace. I usually do this from a bash shell script, and move the original file containing values to be substituted to a new name, and run sed writing the output to my original file name like this:
#!/bin/bash
mv myfile.txt myfile.txt.in
sed -e 's/PatternToBeReplaced/Replacement/g' myfile.txt.in > myfile.txt.
If you don't specify an output, the replacement will go to stdout.
sed -i 's/variable/replacement/g' *.conf
You can use sed to do this:
sed -i 's/toreplace/yoursetting/' configfile
sed is probably available on every unix like system out there. If you want to replace more than one occurence you can add a g to the s-command:
sed -i 's/toreplace/yoursetting/g' configfile
Be careful since this can completely destroy your configfile if you don't specify your toreplace-value correctly. sed also supports regular expressions in searching and replacing.
Look at the UNIX power tools awk, sed, grep and in-place edit of files with Perl.
filepath="/var/start/system/dir1"
searchstring="test"
replacestring="test01"
i=0;
for file in $(grep -l -R $searchstring $filepath)
do
cp $file $file.bak
sed -e "s/$searchstring/$replacestring/ig" $file > tempfile.tmp
mv tempfile.tmp $file
let i++;
echo "Modified: " $file
done
Generally a tool like awk or sed are used for this.
$ sed -i 's/ugly/beautiful/g' /home/bruno/old-friends/sue.txt

Resources