crimso
June 26, 2015, 3:13pm
1
Greetings,
How can I turn this:
t70c7n133 16 t70c7n134 16 t70c7n135 16 t70c7n136 16 t70c7n137 16 t70c7n138 16 t70c7n140 16 t70c7n141 16
into this:
t70c7n133 slots=16
t70c7n134 slots=16
t70c7n135 slots=16
t70c7n136 slots=16
t70c7n137 slots=16
t70c7n138 slots=16
t70c7n140 slots=16
t70c7n141 slots=16
I've come up with a couple ways but they're ugly and I've gotten close with sed but I'm not that good with it. So I'm sure there are much cleaner ways than what I've cooked up.
Thanks in advance.
RudiC
June 26, 2015, 3:28pm
2
Show us what you've cooked up!
For the purpose of simplicity:
xargs -n2 < file|awk '{$2="slots="$2}1'
In pure awk (will fail if there are trailing spaces in the file though :():
awk 'BEGIN{RS=FS};ORS=(NR%2)?" slots=":"\n"{gsub(/\n *$/,"")}1' file
crimso
June 26, 2015, 10:26pm
4
Thank-you pilnet101 for freely chiming in. And yes RudiC I did put forth some effort before posting.
The following variable is inherited:
HOST_LIST='t70c7n133 16 t70c7n134 16 t70c7n135 16 t70c7n136 16 t70c7n137 16 t70c7n138 16 t70c7n140 16 t70c7n141 16'
and I did this:
echo $HOST_LIST | fold -w 13 | sed 's/16/slots=16/'
However I realized that if the 16 was actually a single digit then the fold command is no good. Of course pilnet101's solution works well:
echo $HOST_LIST | awk 'BEGIN{RS=FS};ORS=(NR%2)?" slots=":"\n"{gsub(/\n *$/,"")}1'
Any other suggestions?
With any shell that uses basic Bourne shell syntax:
#!/bin/ksh
HOST_LIST='t70c7n133 16 t70c7n134 16 t70c7n135 16 t70c7n136 16 t70c7n137 16 t70c7n138 16 t70c7n140 16 t70c7n141 16'
set -- $HOST_LIST
while [ $# -ge 2 ]
do printf '%s slots=%s\n' "$1" "$2"
shift 2
done
And with a recent bash
, a 1993 or later version of ksh
, or another shell that supports indexed arrays and arithmetic commands:
#!/bin/ksh
HOST_LIST='t70c7n133 16 t70c7n134 16 t70c7n135 16 t70c7n136 16 t70c7n137 16 t70c7n138 16 t70c7n140 16 t70c7n141 16'
array=( $HOST_LIST )
for ((i = 0; i < ${#array[@]}; i += 2))
do printf '%s slots=%s\n' "${array}" "${array[i+1]}"
done
or with any POSIX-conforming shell that also supports indexed arrays as an extension to the standards:
#!/bin/ksh
HOST_LIST='t70c7n133 16 t70c7n134 16 t70c7n135 16 t70c7n136 16 t70c7n137 16 t70c7n138 16 t70c7n140 16 t70c7n141 16'
array=( $HOST_LIST )
i=0
while [ $i -lt ${#array[@]} ]
do printf '%s slots=%s\n' "${array}" "${array[i+1]}"
i=$((i + 2))
done
All of which produce the output:
t70c7n133 slots=16
t70c7n134 slots=16
t70c7n135 slots=16
t70c7n136 slots=16
t70c7n137 slots=16
t70c7n138 slots=16
t70c7n140 slots=16
t70c7n141 slots=16
Aia
June 26, 2015, 11:23pm
6
As long as they are in pairs, you do not have to worry if the second member of the pair is a single digit or more or no digits at all.
echo $HOST_LIST | awk '{for(i=1;i<=NF;i+=2){printf "%s slots=%s\n", $i, $(i+1)}}'
Looking at coming up with another solution for this in pure shell, similar to Don's solutions - I have been trying to use parameter expansion/substitution. I can only envisage that this would be achievable by doing this only if back references are supported. Looking at several sources online - ksh93 supposedly supports them, can anyone confirm this?
Something along the lines of:
tmp=${HOST_LIST// / strings=}
echo ${tmp//strings=\([![:digit:]]\)/\1"\n"}
pilnet101:
Looking at coming up with another solution for this in pure shell, similar to Don's solutions - I have been trying to use parameter expansion/substitution. I can only envisage that this would be achievable by doing this only if back references are supported. Looking at several sources online - ksh93 supposedly supports them, can anyone confirm this?
Something along the lines of:
tmp=${HOST_LIST// / strings=}
echo ${tmp//strings=\([![:digit:]]\)/\1"\n"}
With the above code, bash
version:
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin14)
and ksh
version:
Copyright (C) 2007 Free Software Foundation, Inc.
version sh (AT&T Research) 93u+ 2012-08-01
produce the output:
t70c7n133 strings=16 strings=t70c7n134 strings=16 strings=t70c7n135 strings=16 strings=t70c7n136 strings=16 strings=t70c7n137 strings=16 strings=t70c7n138 strings=16 strings=t70c7n140 strings=16 strings=t70c7n141 strings=16
1 Like
RudiC
June 27, 2015, 1:06am
9
sed
solution based on you own approach, leaving out fold
:
echo $HOST_LIST | sed -r 's/ ([0-9]+)( |$)/ slots=\1\n/g;s/\n$//'
1 Like
Aia
June 27, 2015, 2:17am
10
$ printf "%s slots=%s\n" $HOST_LIST
t70c7n133 slots=16
t70c7n134 slots=16
t70c7n135 slots=16
t70c7n136 slots=16
t70c7n137 slots=16
t70c7n138 slots=16
t70c7n140 slots=16
t70c7n141 slots=16
5 Likes
Longhand using OSX 10.7.5, default terminal using sh...
#!/bin/sh
# reformat
HOST_LIST='t70c7n133 16 t70c7n134 16 t70c7n135 16 t70c7n136 16 t70c7n137 16 t70c7n138 16 t70c7n140 16 t70c7n141 16'
# Working section.
HOST_LIST=( $HOST_LIST )
for (( n=0; n < ${#HOST_LIST[@]}; n+=2 ))
do
echo "${HOST_LIST[$n]} slots=${HOST_LIST[$((n+1))]}"
done > /tmp/text
# End of working section.
HOST_LIST=$( cat /tmp/text )
echo "$HOST_LIST"
Results:-
Last login: Sat Jun 27 08:18:39 on ttys000
AMIGA:barrywalker~> cd Desktop/Code/Shell
AMIGA:barrywalker~/Desktop/Code/Shell> ./reformat
t70c7n133 slots=16
t70c7n134 slots=16
t70c7n135 slots=16
t70c7n136 slots=16
t70c7n137 slots=16
t70c7n138 slots=16
t70c7n140 slots=16
t70c7n141 slots=16
AMIGA:barrywalker~/Desktop/Code/Shell> _
crimso
June 29, 2015, 7:49am
16
Thank-you all for the variety of solutions.