sed help - nested pattern

Hello,

I am very new to Unix and using sed so I'm struggling a little bit with this command and was hoping someone could help me out.

I want to find a nested pattern in a file and replace some text in that file with text from another file.

For example, in file one I have something like this:

def bikeModels(myBike = getBike())
if myBike == "Huffy":
return ["H1","H2","H3"]
elif myBike == "Mongoose":
return ["M1","M2","M3"]

***Blank line separates these two sections***

def bikeColors(myBike = getBike())
if myBike == "Huffy":
return ["Black","Blue"]
elif myBike == "Mongoose":
return ["Red","White"]

In my file two all I have is a new set of Huffy models:

return ["H4","H5","H6"]

which I want to put into file one, replacing what was originally being returned if myBike == "Huffy" under bikeModels to get a file that looks like this:

def bikeModels(myBike = getBike())
if myBike == "Huffy":
return ["H4","H5","H6"]
elif myBike == "Mongoose":
return ["M1","M2","M3"]

def bikeColors(myBike = getBike())
if myBike == "Huffy":
return ["Black","Blue"]
elif myBike == "Mongoose":
return ["Red","White"]

I can use sed to find the chunk of the file I want with a command like:
sed -n '/bikeModels/,/^$/ {myBike == "Huffy"/,/]/p}; file1

but I have no idea how to replace that text with the text from file two.

I did see I could use:
sed -e '/regex/{r insert.file' -e 'd;}' source
but, again, I have no idea how to combine everything I want to do and have it work.

Thanks to anyone that can help. Let me know if I need to go into more detail or explain anything better.

Try:

awk -vs="$(cat file2)" '
/myBike == "Huffy"/ { change = 1 }
/return/ && change { change = 0; sub(/return.*$/, s) }1' INPUTFILE

Thanks, it's close but it's replacing the Huffy information in both bikeModels and bikeColors. I just want to replace that information in whichever one I specify, in this case bikeModels. I've only used awk for very basic stuff but I'll play around with it for a little while and see if I have better luck than I have had with sed.

Sorry to bump this up but the hurricane meant I wasn't able to check the forums for a few days. Just wondering if anyone else maybe had some insight as to how to go about solving my problem whether it's through sed or awk. Thanks.

Just add one more check:

awk -vs="$(cat file2)" '                                                  
/bikeModels/ { change1 = 1}
/myBike == "Huffy"/ { change2 = 1 }
/return/ && change1 && change2 {
  change1 = change2 = 0
  sub(/return.*$/, s)
}
1' INPUTFILE

Here's how it is done with sed...

sed '/def bikeModels/ {
   N
   /Huffy/ {
      H
      n
      /return/ {
         x
         r file2
         d
      }
   }
}' file1

Thanks so much for replying everyone.
I'm trying to use this command as one line without much luck (I keep getting the message "sed: -e expression #1, char 22: extra characters after command" no matter how I try to reformat the command).

I am entering the command as one line as follows:
sed '/def bikeModels/ { N /Huffy/ { H n /return/ { x r file2 d} } }' file1

Like I said in my post, I am EXTREMELY new to this and kind of got thrown into having to write this command so I'm trying to figure things out on the fly. Should I be able to one line it like that or am I totally doing something wrong? I have tried to move things around/remove spaces in the command but keep getting the same message but with different locations i.e. character 27.

Why do you need to make it a oneliner when the multiliner works just fine.

I'm also using a Python file and need to put the command into something along the lines of commands.getoutput/os.system and just wanted to try to get a one liner in there.

I dont know what you are talking about...unless you provide an example.

I have a Python script where I am running unix commands. In the script I can do something like this:

val = commands.getoutput("/sbin/ifconfig | grep dropped | awk '{split($4, a, \":\"; print a[2]}'").split("\n")

That example runs the command to get the number of dropped packets and assigns that value to val. I probably wouldn't use commands.getoutput for the sed command I had originally posted about since I actually just want to run that command in the Python script without getting any sort of value returned, but that should give you an idea of what I am looking to do...I hope.

Hi.
Use a multiline string literal:

python -c '
from subprocess import call
command = r"""
echo It is a very \
long command
echo "Not really but it could
be"
"""
call(command, shell=True)
'

You can embed python variables using standard python techniques - "%" or "string.Template" or the newest string format possibility.