Tuesday, October 25, 2022

[SOLVED] Bash scripting: sort groups of text below a specific line number

Issue

Text does not need sorting Text does not need sorting Text does not need sorting

  example1.com.:
    sources:
      - config
    targets:
      - route53
  test2.co.uk.:
    sources:
      - config
    targets:
      - route53
  another.net.:
    sources:
      - config
    targets:
      - route53
etc.

If I have a file like the above but with many more domains. Using bash, how could I only sort the text below the "Text does not need sorting" and then also only sort alphabetically by the domain names and not the text in each domain group?

Each group would consist of 5 lines including the domain.

The end result should look like:

  another.net.:
    sources:
      - config
    targets:
      - route53
  example1.com.:
    sources:
      - config
    targets:
      - route53
  test2.co.uk.:
    sources:
      - config
    targets:
      - route53

Solution

Try the following

awk '/^[[:space:]]{2}[[:alpha:]]+.*$/ { key=$1;next } { yaml[key]=yaml[key]"\n"$0 } END { PROCINFO["sorted_in"]="@ind_str_asc";for(i in yaml) { printf "%s%s\n",i,yaml[i] } }' file

Breaking it down:

awk '/^[[:space:]]{2}[[:alpha:]]+.*$/ { # Pattern match each line in the file and check for a new line, 2 spaces and then a domain name.
      key=$1;next                       # Where a match is found, set up an array key and skip to the next line
     } 
     { 
      yaml[key]=yaml[key]"\n"$0         # Set up an array yaml with they key and the value a new line followed by the line
     } 
     END { 
      PROCINFO["sorted_in"]="@ind_str_asc"; # Once the file is processed, sort the index in ascending alphabetical order
      for(i in yaml) {                      
        printf "%s%s\n",i,yaml[i]          # Loop through the yam array and print the sorted index followed by the value
      } 
     }' file


Answered By - Raman Sailopal
Answer Checked By - Senaida (WPSolving Volunteer)