rmkilc
rmkilc

Reputation: 43

Sed with variables and line number restrictions

I have the following file:

<CamcorderProfiles cameraId="0">

    <EncoderProfile quality="720p" fileFormat="mp4" duration="30">
        <Video codec="h264"
               bitRate="8000000"
               width="1280"
               height="720"
               frameRate="30" />
        <Audio codec="aac"
               bitRate="96000"
               sampleRate="48000"
               channels="1" />
    </EncoderProfile>

    <EncoderProfile quality="1080p" fileFormat="mp4" duration="30">
        <Video codec="h264"
               bitRate="12000000"
               width="1920"
               height="1080"
               frameRate="30" />
        <Audio codec="aac"
               bitRate="96000"
               sampleRate="48000"
               channels="1" />
    </EncoderProfile>

</CamcorderProfiles>

<CamcorderProfiles cameraId="1">

    <EncoderProfile quality="720p" fileFormat="mp4" duration="30">
        <Video codec="h264"
               bitRate="8000000"
               width="1280"
               height="720"
               frameRate="30" />
        <Audio codec="aac"
               bitRate="96000"
               sampleRate="48000"
               channels="1" />
    </EncoderProfile>

    <EncoderProfile quality="1080p" fileFormat="mp4" duration="30">
        <Video codec="h264"
               bitRate="12000000"
               width="1920"
               height="1080"
               frameRate="30" />
        <Audio codec="aac"
               bitRate="96000"
               sampleRate="48000"
               channels="1" />
    </EncoderProfile>

</CamcorderProfiles>

Here is my code:

camerastart=$(sed -n '{/<CamcorderProfiles cameraId="0">/=}' $file)
cameraend=$(sed -n $camerastart',$ {/<\/CamcorderProfiles>/=}' $file)

camera1080pstart=$(sed -n $camerastart','$cameraend' {/<EncoderProfile quality="1080p" fileFormat="mp4" duration="30">/=}' $file)

When I print the variables, I get the correct line numbers on all but camera1080p_start, which comes up blank.

camerastart = 3
cameraend = 29
camera1080pstart = 

If I change up the first line of the code to cameraId="1", then I do get proper results for that case.

camerastart = 31
cameraend = 57
camera1080pstart = 45

If I change the code so the first two variables are hardcoded in, I do get the proper output of 17 camera1080pstart.

camerastart="3"
cameraend="29"

camera1080pstart=$(sed -n $camerastart','$cameraend' {/<EncoderProfile quality="1080p" fileFormat="mp4" duration="30">/=}' $file)

Anyone know what is going on?

Upvotes: 1

Views: 231

Answers (3)

rmkilc
rmkilc

Reputation: 43

The solution that worked for me is:

camerastart=$(sed -n '{/<CamcorderProfiles cameraId="0">/=}' $file | head -1)
cameraend=$(sed -n $camerastart',$ {/<\/CamcorderProfiles>/=}' $file | head -1)

camera1080pstart=$(sed -n $camerastart','$cameraend' {/<EncoderProfile quality="1080p" fileFormat="mp4" duration="30">/=}' $file | head -1)

Upvotes: 0

perreal
perreal

Reputation: 98078

Change the second command to:

cameraend=$(sed -n $camerastart',$ {/<\/CamcorderProfiles>/=}' $file | head -1)

because it returns multiple line numbers. However, this might not be the best way to tackle this particular problem.

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 204035

Here's a script that will find and print the line you want to change:

$ cat tst.awk

BEGIN{ FS = "\"" }
/<CamcorderProfiles cameraId=/ { cameraId = $2 }
/<EncoderProfile quality=/     { quality  = $2 }
/bitRate="12000000"/ {
   if ( (cameraId == "0") && (quality == "1080p") ) {
      print NR, "this is the line I want to change:"
      print
   }
}
$ awk -f tst.awk file
17 this is the line I want to change:
               bitRate="12000000"

If you need to be able to invoke it with different cameraId and/or quality and/or any other values, that's a trivial tweak.

If you tell us in what way you want to change the line the script finds, that's trivial too.

EDIT: updated script based on OPs comments below.

$ cat tst.awk
BEGIN{ FS = "\"" }
/<CamcorderProfiles cameraId=/ { cameraId = $2 }
/<EncoderProfile quality=/     { quality  = $2 }
/bitRate="12000000"/ {
   if ( (cameraId == "0") && (quality == "1080p") ) {
      sub(/12000000/,"20000000")
   }
}
{ print }

$ awk -f tst.awk file > tmpfile

$ diff file tmpfile
17c17
<                bitRate="12000000"
---
>                bitRate="20000000"

If you want to update the original file, just run it as:

awk -f tst.awk file > tmpfile && mv tmpfile file

Upvotes: 0

Related Questions