3

I want to sort my channel list in my enigma2 dreambox using bash. The file looks like this:

#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM
#DESCRIPTION new 5[EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM
#DESCRIPTION all  2 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M
#DESCRIPTION movie 3 [EN]

As you can see in the file, each channel consists of two lines. I want to sort two lines each time in bash.

The result should look like this:

#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM
#DESCRIPTION all  2 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M
#DESCRIPTION movie 3 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM
#DESCRIPTION new 5[EN]

First one is all 2 [EN] with the SERVICE above it.

Second is movie movie 3 [EN] with the SERVICE above it.

Third is movie new 5[EN] with SERVICE above it.

I am now using a loop and this is very slow. I think this can be done faster using bash

Possible solution could be, For example:

  • Combine each two lines to one line. Second line needs to be the first and append the above line to it. Result should look like this:

    #DESCRIPTION new 5[EN]#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM
    #DESCRIPTION all  2 [EN]#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM
    #DESCRIPTION movie 3 [EN]#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M
    
  • Sort

  • Create two lines again.
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
simo
  • 41
  • 4
  • First question to clarify: By what do you want to sort the userbouquets file - according to the advisory number in the name of the multimedia files? Second question for clarification: Why did not you put your Bash script on your question at the same time as we could adjust to your needs? The algorithm is very simple. This is an old topic from 2017, so I will not write bash-script, but if you still need it, I will write it. – s3n0 May 20 '18 at 08:51
  • In the bash script, I would first delete all #DESCRIPTION rows because you obviously do not use them (you only have a copy of the name of the stream file). Otherwise, these rows are for expanded info. Of course, you can also handle these #DESCRIPTION rows (as you like). Then I would search in the file names at the end for the number that would sort the data. Since it does not have much (only a few lines), the standard data sorting algorithm will be enough - by comparing the row with all the data content and by shifting the higher number to the lower number and shifting forward (line). – s3n0 May 20 '18 at 08:52

6 Answers6

1

awk and sed:

#!/usr/bin/env bash

awk '/^#SERV/ {s=$0} /^#DESC/ {print s "\t" $0}' |
  sort -t $'\t' -k 2,2 |
  sed 's/\t/\n/'
sjnarv
  • 2,334
  • 16
  • 13
1

Thanks all. two options worked.

option 1

awk '/^#SERV/ {s=$0} /^#DESC/ {print s "\t" $0}' file.txt  | sort -t $'\t' -k 2,2 |sed 's/\t/\n/' 

Option 2

 awk '/#SERVICE/ && getline nl > 0{ print nl"|"$0 | "sort -k2,2 -k3,3" }' /tmp/test.txt   | awk -F'|' '{ print $2 ORS $1}'

I am going to learn now some advanced awk commands

simo
  • 41
  • 4
0

In the next solutions I will use \r between lines joined. In a plain Unix text file you won't have those silly Window things, and it can be replaced with sed or tr. How to join two lines in reverse order? Use rev:

rev inputfile |
   awk '{printf("%s%s",$0,(NR%2==0) ? "\n" : "\r")}' |
   rev | sort | tr '\r' '\n' 

You can avoid reversing the file when you use a sort key. I entered ^M with CTRL-V CRTL-M. I do not trust your letter M after the filenames, perhaps you prefer something like a #

awk '{printf("%s%s",$0,(NR%2==0) ? "\n" : "\r")}' file |
   sort -t'^M' -k2,1 | tr '\r' '\n'
Walter A
  • 19,067
  • 2
  • 23
  • 43
  • command **rev** is not on my Linux dreambox. the second option is giving an error. sort: bad -t parameter. – simo Aug 22 '17 at 22:10
  • Without `rev` you can also try `tac`. When `tac` is missing too, look at https://stackoverflow.com/q/22328828/3220113. Or try finding another sort or try `man sed` and find a way to change the delimiter. Or first replace all spaces by '\r' using 'tr' and insert a space between two lines you are joining with awk, and replace the '\r' by spaces again. – Walter A Aug 23 '17 at 06:20
0

awk solution:

awk '/#SERVICE/ && getline nl > 0{ print nl"|"$0 | "sort -k2,2 -k3,3" }' file 
| awk -F'|' '{ print $2 ORS $1}'

The output:

#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM
#DESCRIPTION all  2 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M
#DESCRIPTION movie 3 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM
#DESCRIPTION new 5[EN]

Additional sed approach:

sed '/#DESCRIPTION/N;{s/\n/|/}' <(tac file) | sort -k2,2 -k3,3 | sed -E 's/(.*)\|(.*)/\2\n\1/'
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
0

With sed:

$ sed -E 'N;s/(.*)\n(.*)/\2\t\1/' infile | sort | sed -E 's/(.*)\t(.*)/\2\n\1/'
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM    
#DESCRIPTION all  2 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M    
#DESCRIPTION movie 3 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM    
#DESCRIPTION new 5[EN]

The first command appends the next line (N), then swaps the first and second line, tab separated. This is then piped to sort, and the second sed command swaps the lines again and replaces the tab with a newline.

This requires that there is no tab character present before processing.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
0

Thanks, I am using the first AWK example (Option 2) and is working good. Which means the file (with "paired" lines (#SERVICE and #DESCRIPTION)) is sorted well.

I do have an other question, regarding a file with the same structure.

Is it possible to expand the sort so, that:

the file is sorted alphabetically (as it does now), but also so that on top of the file first will be ALL the HD Channels (alphabetical sorted), followed by the rest (non-HD channels). HD-channels do have "HD" at the end of the line, starting with "#DESCRIPTION" .

Desired Output Example:

#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Action HD
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Cinema HD
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Family HD
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Action
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Cinema
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Family
ni_hao
  • 404
  • 2
  • 5
  • 16