5

I have a few locations that need the WiFi to be checked daily. Currently when I run my script this is the outcome I get.

The first name corresponds to the first MAC, the first IP and so on. How may I go about re-arranging this file with grep, awk or sed?

Name                : WiFi 1
Name                : WiFi 2
Name                : WiFi 3
Name                : WiFi 4
Name                : WiFi 5
Name                : WiFi 6
Name                : WiFi 7
MAC                 : aa:aa:aa:aa:aa:aa
MAC                 : bb:bb:bb:bb:bb:bb
MAC                 : cc:cc:cc:cc:cc:cc
MAC                 : dd:dd:dd:dd:dd:dd
MAC                 : ee:ee:ee:ee:ee:ee
MAC                 : ff:ff:ff:ff:ff:ff
MAC                 : gg:gg:gg:gg:gg:gg
IP                  : 10.0.1.0
IP                  : 10.0.1.1
IP                  : 10.0.1.2
IP                  : 10.0.1.3
IP                  : 10.0.1.4
IP                  : 10.0.1.5
IP                  : 10.0.1.6
Status              : Operational
Status              : Operational
Status              : Operational
Status              : Operational
Status              : Operational
Status              : Operational
Status              : Operational
Interface           : X2
Interface           : X2
Interface           : X2
Interface           : X2
Interface           : X2
Interface           : X2
Interface           : X2

I'd like them all to output as shown below

Name                : WiFi 1
MAC                 : aa:aa:aa:aa:aa:aa
IP                  : 10.0.1.0
Status              : Operational
Interface           : X2
5
  • 1
    In which way would you want to rearrange it? What is the expected output? What have you tried so far?
    – Kusalananda
    Commented Jan 25, 2017 at 20:34
  • 1
    Why is the first name "obviously " associated to the first MAC & etc?
    – Jeff Schaller
    Commented Jan 25, 2017 at 20:39
  • I updated the post to show the way i'd like it to output. I've tried a using grep and piping it to tail but if I have a site with 3 access points or 12 access points it doesn't work. I also tried to use awk but I don't really know how to use regex.
    – ampadmos
    Commented Jan 25, 2017 at 20:40
  • 7
    Perhaps it makes more sense to adjust how the script outputs, to achieve your desired results. Commented Jan 25, 2017 at 20:42
  • Related: unix.stackexchange.com/questions/195895/…
    – Kusalananda
    Commented Feb 1, 2017 at 6:51

6 Answers 6

13

Self-counting version, season to taste:

awk '    $1!=last {n=0;last=$1}
         {++n;gaggle[n]=gaggle[n]"\n"$0}
         END { for (k in gaggle) print gaggle[k] }
'
3
  • Makes the first AP come out last, but I don't know if it matters.
    – Kusalananda
    Commented Jan 25, 2017 at 22:45
  • @don_crissti Ah, with mawk and gawk it does indeed work fine. I was testing with BSD awk (nawk?) when I commented...
    – Kusalananda
    Commented Jan 25, 2017 at 22:47
  • 3
    awk doesn't guarantee sequence on in results, if it matters you could for (k=1;k<=n;++k) or track the count some other way.
    – jthill
    Commented Jan 25, 2017 at 22:51
10

For seven APs, with GNU sed and bash/ksh:

for (( i = 1; i <= 7; ++i )); do
  sed -n "$i~7p" data
  echo
done

With the provided information in data, this yields

Name                : WiFi 1
MAC                 : aa:aa:aa:aa:aa:aa
IP                  : 10.0.1.0
Status              : Operational
Interface           : X2

Name                : WiFi 2
MAC                 : bb:bb:bb:bb:bb:bb
IP                  : 10.0.1.1
Status              : Operational
Interface           : X2

Name                : WiFi 3
MAC                 : cc:cc:cc:cc:cc:cc
IP                  : 10.0.1.2
Status              : Operational
Interface           : X2

(etc.)

If we don't know how many APs there are, count the Name lines:

num="$( grep -c '^Name' data )"

for (( i = 1; i <= num; ++i )); do
  sed -n "$i~${num}p" data
  echo
done

The GNU sed-specific range syntax first~step will

Match every step'th line starting with line first.

according to the GNU sed manual.

6

Yet another way:

num=$(grep -c ^Name inputfile)
for((i=1; i <= num; i++)); do 
  for((j=1; j < num- 1; j++)); do 
    printf "%dp;" $((i + (j-1)*num)); 
  done; 
  printf "\n"; 
done | while read cmd; do sed -n "$cmd" inputfile; done
2
  • It wasn't as sneaky as I first thought it would be, but neat none the less ;-) You need $num in the printf too where you now have 7, though.
    – Kusalananda
    Commented Jan 25, 2017 at 21:38
  • Ack, thanks @Kusalananda -- leftover from the initial hard coding
    – Jeff Schaller
    Commented Jan 25, 2017 at 21:41
6

Another approach, without awk or sed, cause why not:

split -a 1 -l 7 inputfile && paste -d '\n' x{a,b,c,d,e}
5

Here's another approach in awk.

awk '{a[(NR-1)%7]=a[(NR-1)%7]$0RS}END{for(;i<7;){print a[i++]}}'

Name                : WiFi 1
MAC                 : aa:aa:aa:aa:aa:aa
IP                  : 10.0.1.0
Status              : Operational
Interface           : X2

Name                : WiFi 2
MAC                 : bb:bb:bb:bb:bb:bb
IP                  : 10.0.1.1
Status              : Operational
Interface           : X2
[etc]
1
  • 1
    Actually works with mawk and nawk too. I spot no GNU-isms in it.
    – Kusalananda
    Commented Jan 26, 2017 at 10:26
2

This script will do the job, if I understand the requirements correctly:

#!/usr/bin/zsh

grep Name $1 > /tmp/wifinames
grep MAC $1 > /tmp/wifiMAC
# ...
# add lines for other fields here, you can store the names of files 
# in an array like ['file1', file2',..], and run a for loop printing the nth line inside the
# while loop below


i=1
n=`wc -l /tmp/wifinames|awk '{print $1}'`
# maybe you should run some tests to check if all the files
# produced by grep have equal number of entries 


while [[ $i -le $n ]]; do
    # prints nth line
    sed "${i}q;d" /tmp/wifinames
    sed "${i}q;d" /tmp/wifiMAC
    # ...
    (( i = $i + 1 ))
done
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .