0

Basically every week I have to reverse the following snippet

<!-- Homepage Slider Begin -->
<div class="container-fluid">
  <div class="single-item-home hidden-xs">
    <div class="slide slide--has-caption">
      <a href="/1">
        <img src="/sliders/1_example.jpg">
      </a>
    </div>

    <div class="slide slide--has-caption">
      <a href="/2">
        <img src="/sliders/2_example.jpg">
      </a>
    </div>

    <div class="slide slide--has-caption">
      <a href="/3">
        <img src="/sliders/3_example.jpg">
      </a>
    </div>

    <div class="slide slide--has-caption">
      <a href="/4">
        <img src="/sliders/4_example.jpg">
      </a>
    </div>
  </div>
</div>
<!-- Homepage Slider End -->

Basically I'm wanting to make awk script and have a cron job to essentially take lines 4-8 to swap with lines 22-26 and lines 10-14 swap with lines 16-20 however I can only seem to find a way to swap one line and not line blocks.

Is this even possible with awk or just silly?

NooBskie
  • 3,761
  • 31
  • 51
  • 2
    I think it would be easier to do this on the client side in JS... I agree it is not nice, but easier it is... I always get shivers when hacking (HT|X)ML with [tools that don't respect the proper structure](http://stackoverflow.com/a/1732454/1667004). – ppeterka Aug 29 '16 at 08:57
  • @ppeterka : I agree to what you said. Tools like awk are the last resort. – sjsam Aug 29 '16 at 09:04
  • Can't you use PHP to generate the correct code based on the week number of the year? – Mark Setchell Aug 29 '16 at 09:04
  • @MarkSetchell That would be the ideal solution but the platform im working with only allows static html:( – NooBskie Aug 29 '16 at 10:00

4 Answers4

4

You may use awk . Below script

 awk 'NR==FNR{line[i++]=$0} 
     END{
         for(j=0;j<i;j++){
         if(j>=3 && j<=7){
             print line[j+18];
             continue;
         }
         else if(j>=21 && j<=25){
             print line[j-18];
             continue;
         }
         else if(j>=9 && j<=13){
             print line[j+6];
             continue;
         }
         else if(j>=15 && j<=19){
             print line[j-6];
             continue;
         }
         print line[j];
         }
     }' file

will do what you want.

Sample Output

<!-- Homepage Slider Begin -->
<div class="container-fluid">
  <div class="single-item-home hidden-xs">
    <div class="slide slide--has-caption">
      <a href="/4">
        <img src="/sliders/4_example.jpg">
      </a>
    </div>

    <div class="slide slide--has-caption">
      <a href="/3">
        <img src="/sliders/3_example.jpg">
      </a>
    </div>

    <div class="slide slide--has-caption">
      <a href="/2">
        <img src="/sliders/2_example.jpg">
      </a>
    </div>

    <div class="slide slide--has-caption">
      <a href="/1">
        <img src="/sliders/1_example.jpg">
      </a>
    </div>
  </div>
</div>
<!-- Homepage Slider End -->

Note: I leave the array-bounds check up to you. If the content of the file is static, you may not need this

sjsam
  • 21,411
  • 5
  • 55
  • 102
  • 1
    This works perfectly definitly need to touchup on my `awk` skills – NooBskie Aug 29 '16 at 10:05
  • Unlike C, awk arrays, fields, and strings all start at index 1, not 0. If you write your own arrays with indices that start at 0 it'll be harder for you to avoid mistakes in future when you have to think about how each array was created (manually or automatically) to remember if that array starts at 0 and which at 1. You don't need the `i` variable at all,just use `NR`, and those tests with continues inside a loop should simply be replaced with loops - that'd be clearer and much more efficient. – Ed Morton Aug 29 '16 at 13:27
  • @EdMorton : Thankyou, that was new knowledge for me :-) Also, this stands against general trend in Linux. – sjsam Aug 29 '16 at 13:32
  • 1
    The fact that bash starts arrays at zero doesn't make that situation general, I can't think of any other standard UNIX tool that has arrays so we have one (bash) starting at 0 and the other (awk) starting at 1. Shells are inconsistent because their positional parameters ($1, $2, etc.) start at 1 but their string indices and array indices start at 0, presumably to be the same as C, while awk is consistent within itself in that field numbers ($1, $2, etc.), string indices, and array indices all start at 1. – Ed Morton Aug 29 '16 at 13:40
2
perl -e '@f=<>; print @f[0..2,21..25,8,15..19,14,9..13,20,3..7,26..$#f]' ip.html
  • -e option to pass Perl code from command line itself
  • @f=<> Reads the contents of file (passed as command line argument) into an array
  • and then print as per order required (index starts from 0, $#f gives last index of array @f)
Sundeep
  • 23,246
  • 2
  • 28
  • 103
2

This doesn't care how many lines are in each block or where they start/end in the file and it doesn't require you to store the whole file in memory (though most of the file is the "slides" which DO need to be stored so that's probably a non-issue):

$ cat tst.awk
/<div class="slide/ { inSlide=1; slide="" }
inSlide {
    slide = slide $0 ORS
    if ( /<\/div>/ ) {
        slides[++numSlides] = slide
        inSlide = 0
    }
    next
}
/<\/div>/ {
    for (slideNr=numSlides; slideNr>=1; slideNr--) {
        printf "%s", slides[slideNr]
    }
    numSlides = 0
}
NF

.

$ awk -f tst.awk file
<!-- Homepage Slider Begin -->
<div class="container-fluid">
  <div class="single-item-home hidden-xs">
    <div class="slide slide--has-caption">
      <a href="/4">
        <img src="/sliders/4_example.jpg">
      </a>
    </div>
    <div class="slide slide--has-caption">
      <a href="/3">
        <img src="/sliders/3_example.jpg">
      </a>
    </div>
    <div class="slide slide--has-caption">
      <a href="/2">
        <img src="/sliders/2_example.jpg">
      </a>
    </div>
    <div class="slide slide--has-caption">
      <a href="/1">
        <img src="/sliders/1_example.jpg">
      </a>
    </div>
  </div>
</div>
<!-- Homepage Slider End -->
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

This is a solution, where you define an order where to print in the BEGIN section and in that order it will print:

$ cat > preordered.awk
BEGIN {
    split("1,2,3,22,23,24,25,26,9,16,17,18,19,20,15,10,11,12,13,14,21,4,5,6,7,8",a,",")
} 
{
    b[(NR in a?a[NR]:NR)]=$0
} 
END {
    PROCINFO["sorted_in"]="@ind_num_asc"
    for(i in b)
        print b[i]
}

Give it a go:

$ awk -f preordered.awk' file
<!-- Homepage Slider Begin -->
<div class="container-fluid">
  <div class="single-item-home hidden-xs">
    <div class="slide slide--has-caption">
      <a href="/4">
        <img src="/sliders/4_example.jpg">
      </a>
    </div>
...
James Brown
  • 36,089
  • 7
  • 43
  • 59