1

I want to read out some files and sort the output.

For example:

cat example.conf  
Order: 0   
Package: example 

cat another.conf  
Order: 2  
Package: another

cat file.conf  
Order: 1  
Package: file

I output them with: awk '/Order|Package/' conf/*.conf:

Order: 2  
Package: another  
Order: 0  
Package: example  
Order: 1  
Package: file

I would like the output to be sorted by the number after Order: but without breaking the relation between the lines like:

Order: 0  
Package: example  
Order: 1  
Package: file  
Order: 2  
Package: another
4

If you have GNU awk > 4.0, and assuming the Order record always precedes the Package record, then

gawk '/^Order/ {order = $2} /^Package/ {p[order] = $0} 
  END {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (i in p) {print "Order:", i; print p[i]}
  }
' conf/*.conf
Order: 0
Package: example
Order: 1
Package: file
Order: 2
Package: another

For older gawk you can use asorti:

gawk '/^Order/ {order = $2} /^Package/ {p[order] = $0} 
  END {
    n = asorti(p,b)
    for (i=1;i<=n;i++) {print "Order:", i; print p[b[i]]}
  }
' conf/*.conf
| improve this answer | |
0

Works for files, which contains two lines, only.

sed -n 'N; s/\n//p' *.conf | sort | sed -n 's/\(Package\)/\n\1/p'

Explanation:

  1. sed -n 'N; s/\n//p' *.conf - removes newline between two lines, that is, it joins two contiguous lines in to the one.
  2. sort - sorts long lines, which was made in the previous step.
  3. sed -n 's/\(Package\)/\n\1/p' - returns newline back to its place.

Output:

Order: 0   
Package: example 
Order: 1  
Package: file
Order: 2  
Package: another
| improve this answer | |
0

A naive Unix aproach:

awk '/Order|Package/' conf/*.conf |           # get your usual output
    paste - - |                               # convert two lines to one
        sort -n -k2,2 |                       # sort numerically
            awk '{print $1,$2;print $3,$4}'   # re-print in two columns
| improve this answer | |
0

Python script

#!/usr/bin/env python
from __future__ import print_function
import sys

def get_order_package(filename):
    order=None
    package=None
    with open(filename) as f:
        for line in f:
            if line.startswith('Order:'):
                order=int(line.strip().split()[1])
            if line.startswith('Package:'):
                package=line.strip().replace("Package: ",'')
    return (order,package)

order_list=[]
for argument in sys.argv[1:]:
    order_list.append(get_order_package(argument))
order_list.sort(key=lambda x: x[0])

for i in order_list:
    print('Order:',i[0])
    print('Package:',i[1])

This script defines get_order_package() function which parses the file, and returns tuple in format (integer,package_string). We pass all files as command-line arguments and iterate over them, executing the function explained above for each one. That builds up a list, we sort it, and iterate again, printing each respective tuple parts from the new sorted list.

Test run

$ cat example_1.conf                                               
Order: 0   
Package: example_1

$ cat example_2.conf                                               
Order: 2
Package: example_2

$ cat example_3.conf                                               
Order: 1
Package: example_3

$ ./parse_conf.py  *.conf                                          
Order: 0
Package: example_1
Order: 1
Package: example_3
Order: 2
Package: example_2
| improve this answer | |
0

This works too:

grep -e ^Order -e ^Package `grep ^Order *.conf | awk -F: '{printf("%s:%s\n",$NF,$0);}' |sort| awk -F: '{print $2}'`

Explanation (below multi-line format is only for demonstration, it does not work in bash because the resultant single-line command cannot handle the comments):

$ grep -e ^Order -e ^Package ` \                # grep for lines starting with "Order" or "Package"; start nested command 
> grep ^Order *.conf | \                        # grep for lines starting with "Order" in files *.conf
> awk -F: '{printf("%s:%s\n",$NF,$0);}' | \     # prefixing order number with a separating colon
> sort | \                                      # sort by order number
> awk -F: '{print $2}' \                        # extract file name alone ; now filenames are ordered by the order number contained within them
> `                                             # end nested command
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.