How could I add new string while keeping the tab line? - bash

I tried to add new string using shell script when the code line have "MSG_LOG".
I did add new string at the new line using this shell script,
#!/bin/bash
############Set File Name
fileName=$1
echo ">>>>Set_FileName is done"
echo ">>>>fileName is ${fileName}"
############Get Elements
lineNumArr=(`grep -n "MSG_LOG" $fileName | awk -F ':' '{print $1}'`)
echo ">>>>Getting LineNumArr is done"
for lineNum in "${lineNumArr[#]}"
do
############Replace logger
sed -i "${lineNum} a printf('MSG_Log is show');" $fileName
echo ">>>>Replace_logger is Done"
done
echo ">>>>for loop is closed"
exit
But it doesn't keep tabs on existing lines of code.
For Example, I want to make my .cpp file like this,
#include<iostream>
int main(void){
bool value=true;
....
if(value){
MSG_LOG("VALUE IS TRUE");
printf('MSG_LOG is show');
}
....
But when I actuate this shell script, the result is...
#include<iostream>
int main(void){
bool value=true;
....
if(value){
MSG_LOG("VALUE IS TRUE");
printf('MSG_LOG is show');
}
....
How can I add new code while preserving the tablines?

You should add the same amount of withespace as the previous line when adding a new line.
You want something like this
sed -E 's/^(.*)(MSG_LOG\(.*\);)(.*)$/\1\2\3\n\1printf("MSG_LOG is show");/g'
If I understood correctly.
You don't have to invoke sed once per line as it loops over the entire file.
Also, you need double quotes in printf.

Using sed, you can duplicate the original line containing MSG_LOG and then replace the text, this will keep the tab spacing in place.
$ sed "/MSG_LOG/{p;s/[[:alpha:]].*/printf('MSG_LOG is show');/}" "$fileName"

Related

How to extact value of pattern which is not in comment(another pattern)

Extract "value=" only from non-comment portion
See the below sed expression which gets value from commented code as well
I tried with grep but that doesn't work also
#!/bin/sh
#set -x
FILE="/tmp/comment.txt"
create_file () {
echo "/*" > $FILE
echo "this is a multi" >> $FILE
echo "line with" >> $FILE
echo "var=20" >> $FILE
echo "and ending the comment */" >> $FILE
echo "var=15" >> $FILE # line after comment
}
create_file
cat $FILE
# This sed should extract only from var=15 which is not part of
# comments, how to do that?
# output should be only 15, instead of "20 and 15"
sed -n "s/\(var=\)\([0-9]*\)/\2/p" $FILE
Actual:
/*
this is a multi
line with
var=20
and ending the comment */
var=15
20
15
Expected:
/*
this is a multi
line with
var=20
and ending the comment */
var=15
15
This seems to work:
sed -n -e:a -e'/\*\//d;/\/\*/{N;ba
};s/^var=//p'
The easy part is extracting the value from the line; the hard part is removing the comment first. Rough translation: if there's a */ then delete everything; otherwise if there's a /* then read the next line as well and start over; otherwise if the line starts with "var=" then delete that part and print the rest.
Note 1: that annoying line break may not be needed in your version of sed.
Note 2: I advise you to test this on the command line, before you attempt it from within a script.
This is the cheap and cheerful way to remove comments as you've shown using GNU awk for multi-char RS:
$ awk -v RS='[*]/' -v ORS= '{sub("/[*].*","")}1' file
var=15
It'll strip the comments no matter where they start/stop on each line:
$ cat file
here's some text /* here's a comment */ and more text /* bleh */and more /*
this is a multi
line with
ending here */ and more
var=20/*
and ending the comment */
/* commented */ var=15
$ awk -v RS='[*]/' -v ORS= '{sub("/[*].*","")} 1' file
here's some text and more text and more and more
var=20
var=15
It just can't identify strings that look like comment starts/stops inside strings or other language-specific constructs.
You can pipe that to whatever you like to get the value of var. If that's not all you need then get/use a parser for whatever language your commented code is written in, e.g. see https://stackoverflow.com/a/13062682/1745001 for C/C++.

Replace an unknown string within a line using Bash

I want to be able to modify db001 with a string I pass into the command via CLI. At any given time db001 could be a different value so I can't just look for that value.
./myscript modify_db <new value>
myfile.txt
./myscript modify_db mynewdbname002
Before: database_node=db001.mydomain.local
After: database_node=mynewdbname002.mydomain.local
./myscript modify_db db003
Before: database_node=mynewdbname002.mydomain.local
After: database_node=db003.mydomain.local
You can use this sed command inside your script:
sed "s/^\(database_node=\)[^.]*/\1$1/" file
Example:
s='database_node=db001.mydomain.local'
repl() {
sed "s/^\(database_node=\)[^.]*/\1$1/" <<< "$s";
}
and call it as:
repl mynewdbname002
database_node=mynewdbname002.mydomain.local
repl db003
database_node=db003.mydomain.local
You could have a script like, just like below taking an input argument having the replacement value,
#!/bin/bash
perl -lpe "s/database_node=(\w+)/database_node=$1/g" file
and just do
./script.sh newdbname
Use the -i flag for in-place replacement and -i.bak for in-place replacement with a backup of your original file
perl -lpe -i.bak "s/database_node=(\w+)/database_node=$1/g" file
(or) with a simple bash function
function replaceFile() {
perl -lpe -i.bak "s/database_node=(\w+)/database_node=$1/g" file
}
I would avoid trying to produce the new state from the previous state and rather just use a template :
function modify_db() {
echo "database_node=$1.mydomain.local"
}
I use echo here for illustration but you should obviously do whatever you want to do with the "database_node=$1.mydomain.local".
Supposing it should modify the only line starting with database_node from a file db_conf after having printed the old value :
function modify_db() {
echo "Before: $(grep '^database_node=' db_conf)"
sed -i "s/^database_node=.*\.mydomain\.local/database_node=$1.mydomain.local/" db_conf
echo "After: $(grep '^database_node=' db_conf)"
}

bash: how can I read text in file into string, modify it and save it another file?

I have a file (imaginary):
test() {
echo ${%%NUMBER%%}
}
I need:
Read it into string variable
Replace %%NUMBER%% with number
Save it to another file, maintaining the multi-line architecture.
How I do it:
#!/bin/bash
# Full path of this script
FILE=`readlink -f "${BASH_SOURCE[0]}"`
# This directory path
DIR=`dirname "${FILE}"`
repl() {
STRING=$(cat $DIR/skel.txt)
STRING=$(echo $STRING | sed "s/%%NUMBER%%/$1/")
echo $STRING
}
# try it
repl 50 > ./out.sh
# tried as well:
# repl 50 | tee ./out.sh
# echo "$(repl 50)" > ./out.sh
# STRING=$(echo -e $STRING | sed "s/%%NUMBER%%/$1/")
But I always get everything in one line in out.sh file. Need it to stay multiline, as in source.
Thanks.
Try this:
repl() {
sed "s/%%NUMBER%%/$1/" "$DIR/skel.txt"
}
This is far more efficient, and won't eat your precious newlines.

Add line to Shell Script File

How can I add a line to a shell script, at the very end of a function using bash?
Say the line I want to add is: echo "Well Hello There"; and my function is
function hello_there {
echo "Hi";
echo "Whats popping?";
}
The only real constant will be the name of the method hello_there, and the beginning and end brackets... but I need the line to go above the end bracket... and I do not know how many times I will need to be able to do this...
I would not attempt to dynamically change the source of a script. It's too dangerous. There are several alternatives. The one closest to your problem specification would probably be to write the function like this:
function hello_there {
echo "Hi";
echo "Whats popping?";
${HELLO_THERE_POSTCMD:-true}
}
If you want to change the behaviour of this function, for example to have it recursively erase your home directory, you could set the environment variable
export HELLO_THERE_POSTCOMD="rm -rf $HOME"
before calling your script.
You could look for the closing "}" and replace it with
printf '"Well Hello There"; \n}'
and insert a new line character after the semi colon, also use printf rather than echo
You can regenerate function code as following :
function hello_there {
echo "Hi";
echo "Whats popping?";
}
cmd='echo \"Well\ Hello\ There \"'
type hello_there | tr '\n' ' ' | sed -e "s/.*nction/function/g" | sed -e "s/[(|)]//g" | sed -e "s/\}/\; $cmd\;\}/g"

appending text to specific line in file bash

So I have a file that contains some lines of text separated by ','. I want to create a script that counts how much parts a line has and if the line contains 16 parts i want to add a new one. So far its working great. The only thing that is not working is appending the ',' at the end. See my example below:
Original file:
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
b,b,b,b,b,b
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
b,b,b,b,b,b
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
Expected result:
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,xx
b,b,b,b,b,b
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
b,b,b,b,b,b
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,xx
This is my code:
while read p; do
if [[ $p == "HEA"* ]]
then
IFS=',' read -ra ADDR <<< "$p"
echo ${#ADDR[#]}
arrayCount=${#ADDR[#]}
if [ "${arrayCount}" -eq 16 ];
then
sed -i "/$p/ s/\$/,xx/g" $f
fi
fi
done <$f
Result:
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
,xx
b,b,b,b,b,b
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
b,b,b,b,b,b
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
,xx
What im doing wrong? I'm sure its something small but i cant find it..
It can be done using awk:
awk -F, 'NF==16{$0 = $0 FS "xx"} 1' file
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,xx
b,b,b,b,b,b
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
b,b,b,b,b,b
a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,xx
-F, sets input field separator as comma
NF==16 is the condition that says execute block inside { and } if # of fields is 16
$0 = $0 FS "xx" appends xx at end of line
1 is the default awk action that means print the output
For using sed answer should be in the following:
Use ${line_number} s/..../..../ format - to target a specific line, you need to find out the line number first.
Use the special char & to denote the matched string
The sed statement should look like the following:
sed -i "${line_number}s/.*/&xx/"
I would prefer to leave it to you to play around with it but if you would prefer i can give you a full working sample.

Resources