insert multiple lines in the middle of a file before a specific string using shell script [duplicate] - sed

This question already has answers here:
Insert multiple lines into a file after specified pattern using shell script
(12 answers)
Closed 12 days ago.
I have a log.txt file.The content of the file as below:
Content of the file as below:
properties{
set properties()
}
buildPipeline()
defPipeline(){
execute()
}
Now I have to insert below line just before buildPipeline():
def testbranch= 'feature'
if(env.BRANCH_NAME.startswith(testbranch)){
properties([pipelinetriggers([cron('0 */2 * * 1-5')]),])
}
I tried below .But it is inserting the statements at the end of the file:
sed -i -e "$adef testbranch= 'feature'" log.txt
sed -i -e "$aif(env.BRANCH_NAME.startswith(testbranch)){" log.txt
sed -i -e "$aproperties([pipelinetriggers([cron('0 */2 * * 1-5')]),])" log.txt
sed -i -e "$a}" log.txt
Expected output:
properties{
set properties()
}
def testbranch= 'feature'
if(env.BRANCH_NAME.startswith(testbranch)){
properties([pipelinetriggers([cron('0 */2 * * 1-5')]),])
}
buildPipeline()
defPipeline(){
execute()
}

If ed is available/acceptable, something like:
#!/bin/sh
ed -s log.txt <<-'EOF'
/properties{/;/buildPipeline()/-,c
def testbranch= 'feature'
if(env.BRANCH_NAME.startswith(testbranch)){
properties([pipelinetriggers([cron('0 */2 * * 1-5')]),])
}
.
,p
Q
EOF
Change Q to w if in-place editing is required.
Remove the ,p to silence the output to stdout

This sed command should do the job:
sed -i "
/buildPipeline()/i\\
def testbranch= 'feature'\\
if(env.BRANCH_NAME.startswith(testbranch)){\\
properties([pipelinetriggers([cron('0 */2 * * 1-5')]),])\\
}" log.txt
Note: This is for GNU sed. BSD sed requires the extension for the backup file with -i
Edit after the comment by the OP, which requests that insertion must take place only on the first occurrence of buildPipeline().
If you know the buildPipeline() won't occur on the first line of log.txt:
sed -i "
1,/buildPipeline()/!b
/buildPipeline()/i\\
def testbranch= 'feature'\\
if(env.BRANCH_NAME.startswith(testbranch)){\\
properties([pipelinetriggers([cron('0 */2 * * 1-5')]),])\\
}" log.txt

Related

insert semi colon after 10 digit number

I have lines that start like this: 2141058222 11/22/2017 and I want to append a ; at the end of the ten digit number like this: 2141058222; 11/22/2017.
I've tried sed with sed -i 's/^[0-9]\{10\}\\$/;&/g' which does nothing.
What am I missing?
Try this:
echo "2141058222 11/22/2017" | sed -r 's/^([0-9]{10})/&;/'
echo "2141058222 11/22/2017" | sed 's/ /; /'
Output:
2141058222; 11/22/2017
If the input is always in the format specified, GNU cut works, and might even be more efficient than sed:
cut -c -10,11- --output-delimiter ';' <<< "2141058222 11/22/2017"
Output:
2141058222; 11/22/2017
For an input file that'd be:
cut -c -10,11- --output-delimiter ';' file

sed script to remove everything in brackets over multiple lines

I am trying to use sed script to remove the content of an array in a file. I have tried to delete the content to only leave the brackets (). However I can't get the sed script to work over multiple lines.
I am trying to change the current state of the file:
LIST = ( "content"
"content1"
"content3")
to this:
LIST = ()
However the sed script I am using only changes the file to this:
LIST = ()
"content"
"content1"
"content2"
sed -e 's/LIST=\([^)]*\)/LIST=() /g' filename
I should also mention there are other sets of brackets in the file which I don't want affected.
e.g
LISTNUMBER2("CONTENT")
should not be emptied.
this sed one-liner works for your example:
sed -n '1!H;1h;${x;s/(.*)/()/;p}'
test:
kent$ echo 'LIST = ( "content"
"content1"
"content3")'|sed -n '1!H;1h;${x;s/(.*)/()/;p}'
LIST = ()
if you could use awk, this one-liner works for your example too:
awk -v RS="" '{sub(/\(.*\)/,"()")}1'
test:
kent$ echo 'LIST = ( "content"
"content1"
"content3")'|awk -v RS="" '{sub(/\(.*\)/,"()")}1'
LIST = ()
EDIT for OP's comment
multi brackets situation:
awk
awk -v RS="\0" -v ORS="" '{gsub(/LIST\s*=\s*\([^)]*\)/,"LIST = ()")}1' file
test:
kent$ cat file
LISTKEEP2("CONTENT")
LIST = ( "content"
"content1"
"content3")
LISTNUMBER2("CONTENT")
kent$ awk -v RS="\0" -v ORS="" '{gsub(/LIST\s*=\s*\([^)]*\)/,"LIST = ()")}1' file
LISTKEEP2("CONTENT")
LIST = ()
LISTNUMBER2("CONTENT")
sed:
sed -nr '1!H;1h;${x;s/(LIST\s*=\s*\()[^)]*\)/\1)/;p}' file
kent$ sed -nr '1!H;1h;${x;s/(LIST\s*=\s*\()[^)]*\)/\1)/;p}' file
LISTKEEP2("CONTENT")
LIST = ()
LISTNUMBER2("CONTENT")
Another sed solution:
sed '/LIST = (/{:next;/)/{s/(.*)/()/;b;};N;b next;}'
Here's a version that would not change any block containing a certain string ("keepme" in this example, but could be anything):
sed '/LIST = (/{:next;/)/{/keepme/b;s/(.*)/()/;b;};N;b next;}'
Since this does the keepme test after it finds the closing parenthesis that tag can be anywhere in the block.

Is it possible to tell sed to perform a maximum of one substitution per line?

Is it possible to encapsulate the following pseudocode using sed?
for line in lines:
if line == "foo":
print "FOO"
else:
print "- " + line
Here's the first thing I tried:
> echo 'foo
> bar
> baz' | sed -e 's/^foo$/FOO/' -e 's/^/- /'
- FOO
- bar
- baz
This is incorrect since both substitutions are applied to the first line.
Is it possible to tell sed to perform a maximum of one substitution per line?
You can limit what lines a substitution affects, by prefixing it with a pattern:
sed -e '/^foo$/! s/^/- /' -e '/^foo$/ s//FOO/' infile
A better alternative is to use the t branch command which will go to the next line if the previous substitution succeeded:
sed 's/^foo$/FOO/; t; s/^/- /' infile
Or the more portable:
sed -e 's/^foo$/FOO/' -e t -e 's/^/- /' infile
Output in both cases:
FOO
- bar
- baz

Unix - Removing everything after a pattern using sed

I have a file which looks like below:
memory=500G
brand=HP
color=black
battery=5 hours
For every line, I want to remove everything after = and also the =.
Eventually, I want to get something like:
memory:brand:color:battery:
(All on one line with colons after every word)
Is there a one-line sed command that I can use?
sed -e ':a;N;$!ba;s/=.\+\n\?/:/mg' /my/file
Adapted from this fine answer.
To be frank, however, I'd find something like this more readable:
cut -d = -f 1 /my/file | tr \\n :
Here's one way using GNU awk:
awk -F= '{ printf "%s:", $1 } END { printf "\n" }' file.txt
Result:
memory:brand:color:battery:
If you don't want a colon after the last word, you can use GNU sed like this:
sed -n 's/=.*//; H; $ { g; s/\n//; s/\n/:/g; p }' file.txt
Result:
memory:brand:color:battery
This might work for you (GNU sed):
sed -i ':a;$!N;s/=[^\n]*\n\?/:/;ta' file
perl -F= -ane '{print $F[0].":"}' your_file
tested below:
> cat temp
abc=def,100,200,dasdas
dasd=dsfsf,2312,123,
adasa=sdffs,1312,1231212,adsdasdasd
qeweqw=das,13123,13,asdadasds
dsadsaa=asdd,12312,123
> perl -F= -ane '{print $F[0].":"}' temp
abc:dasd:adasa:qeweqw:dsadsaa:
My command is
First step:
sed 's/([a-z]+)(\=.*)/\1:/g' Filename |cat >a
cat a
memory:
brand:
color:
battery:
Second step:
sed -e 'N;s/\n//' a | sed -e 'N;s/\n//'
My output is
memory:brand:color:battery:

How can I add the current date or time to end of each line in file?

I have a file called data.txt.
I want to add the current date, or time, or both to the beginning or end of each line.
I have tried this:
awk -v v1=$var ' { printf("%s,%s\n", $0, v1) } ' data.txt > data.txt
I have tried this:
sed "s/$/,$var/" data.txt
Nothing works.
Can someone help me out here?
How about :
cat filename | sed "s/$/ `date`/"
The problem with this
awk -v v1=$var ' { printf("%s,%s\n", $0, v1) } ' data.txt > data.txt
is that the > redirection happens first, and the shell truncates the file. Only then does the shell exec awk, which then reads an empty file.
Choose one of these:
sed -i "s/\$/ $var/" data.txt
awk -v "date=$var" '{print $0, date}' data.txt > tmpfile && mv tmpfile data.txt
However, does your $var contain slashes (such as "10/04/2011 12:34") ? If yes, then choose a different delimiter for sed's s/// command: sed -i "s#\$# $var#" data.txt