How to replace values in a file using sed - linux

I need to replace few values and remove the "#" symbol for this lines in the below file using sed in my shell script.
Below are the lines to be replaced:
#RateLimitInterval = 30s
#RateLimitBurst = 1000
Replacement value:
RateLimitInterval = 60s
RateLimitBurst = 10000
File is as below
#Storage=auto
#Compress=yes
#Seal=yes
#SplitMode=uid
#SyncIntervalSec=5m
#RateLimitInterval=30s
#RateLimitBurst=1000
#SystemMaxUse=
#SystemKeepFree=
#SystemMaxFileSize=
#RuntimeMaxUse=
#RuntimeKeepFree=
#RuntimeMaxFileSize=
#MaxRetentionSec=
#MaxFileSec=1month
#ForwardToSyslog=yes
#ForwardToKMsg=no
#ForwardToConsole=no
#ForwardToWall=yes
#TTYPath=/dev/console
#MaxLevelStore=debug
#MaxLevelSyslog=debug
#MaxLevelKMsg=notice
#MaxLevelConsole=info
#MaxLevelWall=emerg
#LineMax=48K
The code which I wrote:
sed -i.bk '/#RateLimit/ s/#//; /RateLimitInterval/ s/30s/60s/; /RateLimitBurst/ s/1000/10000/' check_jounal.conf
Can Someone provide me suggestions to optimize this code, feel like it is too long !!

I would just spell out the replacements in their entirety:
sed \
-e 's/^#RateLimitInterval=30s$/RateLimitInterval=60s/' \
-e 's/^#RateLimitBurst=1000$/RateLimitBurst=10000/'
By default, sed accepts its input on standard input and writes to standard output. You can add a filename to read the original from a file; add --in-place (-i) to also write the replacement to the same file.

sed -e '/RateLimitInterval/{s/30/60/; s/^#//;}' \
-e '/RateLimitBurst/{s/1000/10000/; s/^#//;}'
I strongly recommend against using -i. It seems a bit fragile to try to match the current RHS on each line, so you might prefer s/=.*/=60/' and s/=.*/=10000/'

Related

sed replace string with space and special characters

The test23 file contains a line
root_url = %(protocol)s://%(domain)s:%(http_port)s/
I need to replace this with
root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana
This below steps in the script doesn't work.
line_old='root_url = %(protocol)s://%(domain)s:%(http_port)s/'
line_new='root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana'
sed -i "s/\${line_old}\/\${line_new}/\g" test23
Try changing delimiter of sed:
sed -i "s|${line_old}|${line_new}|g" test23
example
echo "${line_old}" | sed "s|${line_old}|${line_new}|g"
root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana
I would use:
sed '/^root_url[ ][=]/s/$/grafana/' filename
Where:
/^root_url[ ][=]/ locates the line beginning with "root_url =", then
the normal substitution form 's/$/grafana/' simply appends "grafana" to the end of the line.
(note: add -i to edit the file in-place, or add -i.bak to edit in-place preserving a copy of the original file unchanged in filename.bak)
Results
root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana
Look things over and let me know if that meets your needs and if you have any questions.

Cannot replace string from a file with another string shell

I have a file filename with 2 lines:
2018-Feb-22 06:02:01.1234|AVC-00123HHGF|427654|Default|Name1 [1]|2334|2344444|(00:00:00.45567)|
2018-Feb-22 07:02:01.1234|BCV-00123HHGF|427654|Default|Name1 [1]|2334|2344444|(00:00:00.45567)|
I want to concat string
"Warning: Time elapsed:,3444, is smaller than Name2:44222"
At the end of the line which is equal with
Var1="2018-Feb-22 06:02:01.1234|AVC-00123HHGF|427654|Default|Name1 [1]|2334|2344444|(00:00:00.45567)|"
Or has the following pattern
Var2="2018-Feb-22 06:02:01.1234|AVC-00123HHGF|"
And then filename will contain
2018-Feb-22 06:02:01.1234|AVC-00123HHGF|427654|Default|Name1 [1]|2334|2344444|(00:00:00.45567)|"Warning: Time elapsed:,3444, is smaller than Name2:44222"
2018-Feb-22 07:02:01.1234|BCV-00123HHGF|427654|Default|Name1 [1]|2334|2344444|(00:00:00.45567)|
This is what i've tried:
Var3='2018-Feb-22 06:02:01.1234|AVC-00123HHGF|427654|Default|Name1 [1]|2334|2344444|(00:00:00.45567)|"Warning: Time elapsed:,3444, is smaller than Name2:44222"'
sed -i 's/'"$Var1"'/'"$Var3"'/' filename
sed -i "s/$Var1/$Var3/" filename
Var4='"Warning: Time elapsed:,3444, is smaller than Name2:44222"'
sed -i "/$Var1/a $Var4" filename
But nothing happens. Not even an error.
It's there any other way to do this? I need to keep the same order of the lines within filename.
UPDATE: i've gave up on using sed and tried a less optimal solution, but it works.
I have 2 files:
File_to_change
File_with_lines_to_add
While read line; do
Prkey=##calculate pk
N=0
While read linetoadd; do
Prmkey=##calculate pk
If [ "$Prkey" =="$Prmkey" ]; then
N=1
echo "$line$linetoadd">>outfile
Fi
Done < File_with_lines_to_add
If [ "$N" == "0" ]; then
echo "$line">>outfile
Fi
Done < File_to_change
suffix="Warning: Time elapsed:,3444, is smaller than Name2:44222"
pattern="AVC-"
sed -E "/$pattern/s/^(.*)$/\1$suffix/" filename
2018-Feb-22 06:02:01.1234|AVC-00123HHGF|427654|Default|Name1 [1]|2334|2344444|(00:00:00.45567)|Warning: Time elapsed:,3444, is smaller than Name2:44222
2018-Feb-22 07:02:01.1234|BCV-00123HHGF|427654|Default|Name1 [1]|2334|2344444|(00:00:00.45567)|
sed -E : -E allows later usage of () for grouping, without masking
"..." : the command. Double qoutes allow $x expressions to be evaluated by the shell, before sed gets them to read
/$pattern/ : look for this pattern and only act, if pattern is found
s/a/b/ : substitute expression a with b
/^(.*)$/ : our a-expression
^ Start of line
(.*) : an arbitrary character, and in arbitrary count, captured as a group for later reference as \1, since it's the first group.
$ : end of line
/\1$suffix/ : our b-expression
\1 : what matched above the (.*) pattern
$suffix : what was replaced by the shell
filename
Note that many keywords (better key-characters, since most of them are only 1 character long) change their meaning by context, and quotation is important, and flags like -E, -i, -r.
For example, the $ can be interpreted by the shell, but if not touched, in can mean 'end of line' or 'last line' or 'Dollar Sign'.
'+' can mean at least one, '.' can mean 'any character', a \ is used for masking in sed, to introduce back references like \1. It's a mass but very useful to learn.
Use sed with care.
The vertical bar in "34|AVC-00123HHGF|42" will be interpreted by sed als alternative, either 4 or A and either F or 4. So that would match:
"34VC-00123..."
"3AVC-00123.."
"...HHGF2"
"...HHG42"
which makes for 4 combinations of 2x2 alternatives, none of them matching "34|AVC-00123HHGF|42". How to handle that? Well - masking:
"34\|AVC-00123HHGF\|42"
which might again be done by other sed programs, but you guess where that leads to.
"34.AVC-00123HHGF.42" would match, so make reasonable paranoid decisions, and test and control. :)
Try this:
sed -i '' '/2018-Feb-22 06:02:01.1234|AVC-00123HHGF|/s/$/\"Warning: Time elapsed:,3444, is smaller than Name2:44222\"/' gilename
If that doesn't work, retreat to something simpler, tell us what happens when you try this:
sed 's/2018/XXXX/' filename

Sed: Replacing Date Format

I have a text file where there is a date string of "2014-06-01T03:11:00Z " in every line. I would like to replace that with "2014-06-01 03:11Z " using sed.
I've been trying to use this code but, it's failing me:
sed -i 's/[0-9]-[0-9]-[0-9]T[0-9]:[0-9]:[0-9]Z/[0-9]-[0-9]-[0-9] [0-9]:[0-9]Z/g' \
/home/aaron/grads/data/metars/${YMD}/latest.metars
Your digit sub-expressions only match a single digit, but the date contains 2 or 4 digits. A simple version that would match dates is:
sed -i 's/\([0-9]*-[0-9]*-[0-9]*\)T\([0-9]*:[0-9]*\):[0-9]*Z/\1 \2Z/g' \
/home/aaron/grads/data/metars/${YMD}/latest.metars
However, this matches zero or more digits at each position where digits are expected. You really want to insist on the correct number of digits in each segment. A more refined version is:
sed -i 's/\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\)T\([0-9]\{2\}:[0-9]\{2\}\):[0-9]\{2\}Z/\1 \2Z/g' \
/home/aaron/grads/data/metars/${YMD}/latest.metars
And since your sed supports -i without specifying a back-up suffix (so it is probably GNU sed), you can probably abbreviate that to:
sed -r -i 's/([0-9]{4}-[0-9]{2}-[0-9]{2})T([0-9]{2}:[0-9]{2}):[0-9]{2}Z/\1 \2Z/g' \
/home/aaron/grads/data/metars/${YMD}/latest.metars
Try this GNU sed command to replace all the lines which contains the date string with the string you mentioned,
sed -ri 's/^.*([0-9]{4})-([0-9]{2})-([0-9]{2})\w*([0-9]{2}):([0-9]{2}):([0-9]{2})(.)(.*)$/\1-\2-\3 \4:\5\7/g' file
Example:
$ cat aa
jgklj 2014-06-01T03:11:00Z jhgkjhvk
blaf 2015-12-08T03:15:02Z bvcjghj
$ sed -r 's/^.*([0-9]{4})-([0-9]{2})-([0-9]{2})\w*([0-9]{2}):([0-9]{2}):([0-9]{2})(.)(.*)$/\1-\2-\3 \4:\5\7/g' aa
2014-06-01 03:11Z
2015-12-08 03:15Z
For to replace date only and print all the other text as it is then run the below command.
sed -ri 's/^(.*)([0-9]{4})-([0-9]{2})-([0-9]{2})\w*([0-9]{2}):([0-9]{2}):([0-9]{2})(.)(.*)$/\1\2-\3-\5 \5:\6\8\9/g' file
Example:
$ cat aa
jgklj 2014-06-01T03:11:00Z jhgkjhvk
blaf 2015-12-08T03:15:02Z bvcjghj
$ sed -r 's/^(.*)([0-9]{4})-([0-9]{2})-([0-9]{2})\w*([0-9]{2}):([0-9]{2}):([0-9]{2})(.)(.*)$/\1\2-\3-\5 \5:\6\8\9/g' aa
jgklj 2014-06-03 03:11Z jhgkjhvk
blaf 2015-12-03 03:15Z bvcjghj
You can use this method also
$-sed -r 's/^([^T]+).((.*):){1,2}.([^Z])/\1 \3/g'

how to edit a line using sed or awk in linux containing a certain number or string

My Stress.k file is as follows
180.4430
*INCLUDE
$# filename
*STRESS_INITIALIZATION
*END
I want it to be like
180.4430
*INCLUDE
$# filename
*STRESS_INITIALIZATION
*/home/hassan/534.k
*END
for that I used sed as follows
a="$(cat flow.k)"
sed -i -e '/*END/i \*/home/hassan/$a.k ' Stress.k
where flow.k has only a single number like 534.k or something . Here sed put the line before END but it doesn't take the value of a , instead it puts the same alphabet and it doesn't understand $a.k.
Please also tell me how to delete the second last line or the line with a string hassan for example so that I can delete it first and the for the next step I use it to enter my required line.
if possible please also suggest the alternatives.
best regards
bash variables are only replaced when in double quotes, e.g.
sed -i -e "/*END/i \*/home/hassan/$a.k " Stress.k
Use double quotes to allow the variable to be expanded.
sed -i -e "/*END/i \*/home/hassan/$a.k " Stress.k
To replace the string, do it as you read in the file:
a=$(sed 's/534/100/' flow.k)
To delete a line:
sed '/hassan/d' inputfile
To read a file into the stream after the current line:
sed '/foo/r filename' inputfile

sed script to remove file name duplicates

I hope the below task will be very easy for sed lovers. I am not sed-guru, but I need to express the following task in sed, as sed is more popular on Linux systems.
The input text stream is something which is produced by "make depends" and looks like following:
pgm2asc.o: pgm2asc.c ../include/config.h amiga.h list.h pgm2asc.h pnm.h \
output.h gocr.h unicode.h ocr1.h ocr0.h otsu.h barcode.h progress.h
box.o: box.c gocr.h pnm.h ../include/config.h unicode.h list.h pgm2asc.h \
output.h
database.o: database.c gocr.h pnm.h ../include/config.h unicode.h list.h \
pgm2asc.h output.h
detect.o: detect.c pgm2asc.h pnm.h ../include/config.h output.h gocr.h \
unicode.h list.h
I need to catch only C++ header files (i.e. ending with .h), make the list unique and print as space-separated list prepending src/ as a path-prefix. This is achieved by the following perl script:
make libs-depends | perl -e 'while (<>) { while (/ ([\w\.\/]+?\.h)/g) { $a{$1} = 1; } } print join " ", map { "src/$_" } keys %a;'
The output is:
src/unicode.h src/pnm.h src/progress.h src/amiga.h src/ocr0.h src/ocr1.h src/otsu.h src/barcode.h src/gocr.h src/../include/config.h src/list.h src/pgm2asc.h src/output.h
Please, help to express this in sed.
Not sed but hope this helps you:
make libs-depends | grep -io --perl-regexp "[\w\.\/]+\.h " | sort -u | sed -e 's:^:src/:'
If you really want to do this in pure sed:
make libs-depends | sed 's/ /\n/g' | sed '/\.h$/!d;s/^/src\//' | sed 'G;/^\(.*\)\n.*\1/!h;$!d;${x;s/\n/ /g}'
The first sed command breaks the output up into separate lines, the second filters out everything but *.h and prepends 'src/', the third gloms the lines together without repetition.
Sed probably isn't the best tool here as it's stream-oriented. You could possibly use it to convert the spaces to newlines though, pipe that through sort and uniq, then use sed again to convert the newlines back to spaces.
Typing this on my phone, though, so can't give exact commands :(

Resources