Home > Back-end >  set multiples lines in a "concatenate blocks"
set multiples lines in a "concatenate blocks"

Time:12-15

i have a list of pmox server (and multiple other things). The list is an output command who give :

server1
server2
server3
server4
server5
pmox02
pmox03
pmox04
pmox06
pmox07
pmox08
pmox10
pmox11
pmox12
pmox13
pmox14
pmox15
pmox16
pmox17
pmox18
pmox19
pmox20
pmox21
pmox22
pmox23
pmox24
pmox25
pmox26
pmox27
pmox28
pmox29
pmox30
pmox31
pmox32
pmox33
pmox34
pmox35
pmox36
pmox37
pmox38
pmox39
pmox40
pmox41
pmox42
pmox43
pmox44
pmox45
pmox46
pmox47
pmox48
pmox49
pc1
pc2
pc3
pc4

That i would like to have in the output is something who concatenate the output of my command like this :

server1 server2 server3 server4 server5
pmox02 pmox03 pmox04 pmox06 pmox07 pmox08 pmox10 
pmox11 pmox12 pmox13 pmox14 pmox15 pmox16 pmox17 pmox18 pmox19
pmox20 pmox21 pmox22 pmox23 pmox24 pmox25 pmox26 pmox27 pmox28 pmox29
pmox30 pmox31 pmox32 pmox33 pmox34 pmox35 pmox36 pmox37 pmox38 pmox39
pmox40 pmox41 pmox42 pmox43 pmox44 pmox45 pmox46 pmox47 pmox48 pmox49
pc1 pc2 pc3 pc4

I don't have really no idea of how to output the command this way. Appreciate any help ^^

CodePudding user response:

With GNU awk:

awk '{match($0, /^([a-z] )([0-9] )/, a)
    if (p && p != a[1]) {printf "\n%s ", $0}
    if (a[2] % 10 == 0) {print a[1]a[2]}else{printf "%s ", $0}
    p=a[1]}
    END{print}
' file

Output

server1 server2 server3 server4 server5 
pmox02 pmox02 pmox03 pmox04 pmox06 pmox07 pmox08 pmox10
pmox11 pmox12 pmox13 pmox14 pmox15 pmox16 pmox17 pmox18 pmox19 pmox20
pmox21 pmox22 pmox23 pmox24 pmox25 pmox26 pmox27 pmox28 pmox29 pmox30
pmox31 pmox32 pmox33 pmox34 pmox35 pmox36 pmox37 pmox38 pmox39 pmox40
pmox41 pmox42 pmox43 pmox44 pmox45 pmox46 pmox47 pmox48 pmox49 
pc1 pc1 pc2 pc3 pc4 pc4

CodePudding user response:

The question lacks details on what structure the input has (whether it is always one token per line) and what should happen e.g. when tokens don’t end with a digit, when they are only 1 character long etc. Importantly, it doesn’t say whether the lines always come grouped and sorted or not…

Assuming that (1) you want to group (print on a single line) lines that differ only by the last character and that (2) the input is always grouped by prefix and sorted, you can simply read lines into an array and print out the array each time you encounter a different prefix for the first time. This is in pure Bash; no external processes involved:

#!/bin/bash
set -euo pipefail

last_prefix=
tokens=()
while IFS= read -r token; do
  new_prefix="${token:: -1}"
  if [[ "$new_prefix" == "$last_prefix" ]]; then
    tokens =("$token")
  else
    (( ${#tokens[@]} )) && printf '%s\n' "${tokens[*]}" || :
    last_prefix="$new_prefix"
    tokens=("$token")
  fi
done
(( ${#tokens[@]} )) && printf '%s\n' "${tokens[*]}" || :

However, your example output differs from this solution’s output by putting pmox10 on the previous line. Not sure why that should happen. Is that a special case? No idea.

server1 server2 server3 server4 server5
pmox02 pmox03 pmox04 pmox06 pmox07 pmox08
pmox10 pmox11 pmox12 pmox13 pmox14 pmox15 pmox16 pmox17 pmox18 pmox19
pmox20 pmox21 pmox22 pmox23 pmox24 pmox25 pmox26 pmox27 pmox28 pmox29
pmox30 pmox31 pmox32 pmox33 pmox34 pmox35 pmox36 pmox37 pmox38 pmox39
pmox40 pmox41 pmox42 pmox43 pmox44 pmox45 pmox46 pmox47 pmox48 pmox49
pc1 pc2 pc3 pc4
  • Related