How to sort by complex algorithm

Hello,

To simplify ma question, here is my list :

# cat liste
  a
  m
  x
  h

and here is the right order to list his component :

liste_order="1:m 2:a 3:h 4:x"

The only way to sort my file like I want, I find this idea :

cat liste |  sed 's/a/2:a/g' | sed 's/m/1:m/g' | sed 's/h/3:h/g' | sed 's/x/4:x/g'   | sort

But, it's very complex.

Have anyone any better idea ?
( I simplify my problem, my file is big...)

Thanks in advance.

And what decides the right order???

With Perl:

perl  -lne'BEGIN {
  %liste_order = reverse @{ [split /[\s+:]/, "1:m 2:a 3:h 4:x"] };
  }
  push @data, $_ =~ /(\w+)/;
  print join $/, sort { 
     $liste_order{$a} <=> $liste_order{$b} 
       } @data 
    if eof
    ' liste

Thank you for your answer, but I cannot use PERL...
Is there any idea by SHELL ?

Many thanks in advance.

The shell is not the right tool for this task, why not Perl?

Because, i don't understand it, so i cannot adapt it to my real case.
i just simplify it
real case is a bit different, and i don't know how to adapt your perl script:

1) in your script how to replace "1:m 2:a 3:h 4:x" by a variable ( a shell variable" liste_order which I prepare in advance.

2) Unstead of a file "liste" my input came from another script execution.
Let's say "command.sh"
How, can I use your perl with the ouput of "command.sh" unstead a file "liste"
( i cannot put a outout of command.sh on a liste file for many reason)

With shell i can adapt any solution to my cadr, with perl i cannot ....
Thanhs in advance.

You could try something like this:

export liste_order='1:m 2:a 3:h 4:x'
./command.sh | 
  perl  -lne'BEGIN {
    %liste_order = reverse @{ [split /[\s+:]/, $ENV{liste_order}] };
    }
    push @data, $_ =~ /(\w+)/;
    print join $/, sort { 
      $liste_order{$a} <=> $liste_order{$b} 
        } @data 
     if eof
    ' 

Many, many thanks.
I have a last question :
In real case, I will compare "1:m" with input line begining with "m" ( not equal to "m")
how can I do it ?
This is my last question and thank you very much

try this..

# liste_order="1:m 2:a 3:h 4:x" ; echo "$liste_order">liste_order
# awk 'NR==FNR{num=gsub(FS,"");a[$0]=num;next}{for(i=1;i<=NF;i++)for(j in a)if($i~j){sub(":.","",$i);for(s=1;s<=a[j];s++)ss=ss FS;print ss$i":"j;ss=""}}' liste liste_order
  1:m
  2:a
  3:h
  4:x

regards
ygemici

export liste_order='1:m 2:a 3:h 4:x'
./command.sh | 
  perl -lne'BEGIN {
    %liste_order = reverse @{ [split /[\s+:]/, $ENV{liste_order}] };
    }
    push @data, [substr($_, 0, 1), $_];
    print join $/, map $data[$_]->[1], sort { 
      $liste_order{$data[$a]->[0]} <=> $liste_order{$data[$b]->[0]} 
        } 0..$#data 
          if eof
    '    

Or this (it should be less efficient):

export liste_order='1:m 2:a 3:h 4:x'
./command.sh | 
  perl -lne'BEGIN {
    %liste_order = reverse @{ [split /[\s+:]/, $ENV{liste_order}] };
    }
    push @data, $_;
    print join $/, map $data[$_], sort { 
      $liste_order{substr($data[$a], 0, 1)} <=> $liste_order{substr($data[$b], 0, 1)} 
        } 0..$#data 
          if eof
    '