0

Need your help, my command output is :

Server1:  
CPU(S):  8  
RAM: 24  
Socket: 2  

Server2:  
CPU(S):  16   
RAM: 32   
Socket: 5 

Desired Output:

Server1:,8,24,2  
Server2:,16,32,5    
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255

6 Answers6

2
awk '
  NF==1 { printf "%s%s", NR==1 ? "" : ORS, $1 }
  NF==2 { printf ",%s", $2 }
  END   { printf "%s", ORS }
' file
  • If the line contains one field:
    • print a newline if this is not the first line
    • print field1
  • If the line contains two fields, print a comma and field2
  • Finally, print a newline
Freddy
  • 25,565
1
$ awk -v RS= -v OFS=',' '{print $1, $3, $5, $7}' file
Server1:,8,24,2
Server2:,16,32,5
Ed Morton
  • 31,617
0
# will be used to remember the previous line
b=;
while read -r a; do 
 # if the previous line was empty, then this line is a title line
 if [ "$b" == "" ]; 
  then echo;
  echo -n $a; 
 # else only output everything after ": "
 else IFS=": " read -r _ digs <<< "$a"; 
 # don't want to output a comma for a blank line
  if [ "$a" != "" ]; 
   then echo -n ,$digs;
  fi;
 fi;
 b=$a; 
done < 2

Output:

 
Server1:,8,24,2  
Server2:,16,32,5 

If you'd like to get rid of the space in the beginning or add a blank line at the end, there are a couple of ways to do it, that would make this script a bit more complicated. Let me know if you can't figure out how to do it.

Alex
  • 1,175
0

sed solution.

$ cat file.txt
Server1:
CPU(S):  8
RAM: 24
Socket: 2

Server2:
CPU(S):  16
RAM: 32
Socket: 5
$ sed -n '/^Server/{s/ *$//;N;s/\n.*: */,/;s/ *$//;N;s/\n.*: */,/;s/ *$//;N;s/\n.*: */,/;p}' file.txt
Server1:,8,24,2
Server2:,16,32,5
$
steve
  • 21,892
0

With a sufficiently recent1 version of Miller

mlr --idkvp --irs '\n\n' --ifs '\n' --ips ':' --ocsvlite --headerless-csv-output \
  clean-whitespace then put 'x=$[[1]]; $[[1]]="1"; $1=x' then remove-empty-columns \
  inputfile

Explanation:

  • --idkvp --irs '\n\n' --ifs '\n' --ips ':' --ocsvlite --headerless-csv-output set the input format to paragraph mode with key-value pairs separated by the colon character and one field per line; set the output format to csvlite and suppress printing of the field name header

  • clean-whitespace strip leading and trailing whitespace form the field values

  • put 'x=$[[1]]; $[[1]]="1"; $1=x' set the value of the first field equal to its name2 and set its name to "1" . The latter is important since it homogenizes the records - otherwise Miller prints each record as a separate CSV block, even when --headerless-csv-output is in effect.

  • remove-empty-columns since with --irs '\n\n' --ifs '\n', a single newline after the final record is treated as a trailing empty field - this kludge removes it

If you want the : to be preserved as part of the first field value, then change $1=x to $1=x.":" in the put clause.

Testing:

$ ~/src/miller/c/mlr --idkvp --irs '\n\n' --ifs '\n' --ips ':' --ocsvlite --headerless-csv-output \
>   clean-whitespace then put 'x=$[[1]]; $[[1]]="1"; $1=x' then remove-empty-columns \
>   inputfile
Server1,8,24,2
Server2,16,32,5

or preserving the : in the server name:

$ ~/src/miller/c/mlr --idkvp --irs '\n\n' --ifs '\n' --ips ':' --ocsvlite --headerless-csv-output \
>   clean-whitespace then put 'x=$[[1]]; $[[1]]="1"; $1=x.":"' then remove-empty-columns \
>   inputfile
Server1:,8,24,2
Server2:,16,32,5

1 works in Miller 5.6.2-dev but not in Miller 5.3.0

2 note that although it looks like it should be possible to do the name-value swap without the temporary variable as

 put '$[ $[[1]] ]=$[[1]]; $[[1]]="1"'

this appears to have the side effect of creating an additional empty-valued in-stream variable with a non-printable name.

steeldriver
  • 81,074
0

Using awk in paragraph mode :

awk -v RS= 'gsub(/\n[^:]+: */, ",")' file

 Server1:,8,24,2
 Server2:,16,32,5