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
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
awk '
NF==1 { printf "%s%s", NR==1 ? "" : ORS, $1 }
NF==2 { printf ",%s", $2 }
END { printf "%s", ORS }
' file
$ awk -v RS= -v OFS=',' '{print $1, $3, $5, $7}' file
Server1:,8,24,2
Server2:,16,32,5
# 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.
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
$
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.
Using awk in paragraph mode :
awk -v RS= 'gsub(/\n[^:]+: */, ",")' file
Server1:,8,24,2
Server2:,16,32,5
printf "%s", ORS
=print ""
. – Ed Morton Dec 20 '19 at 20:06