1

I'm trying to create a script for automatic device creation. I'm pretty far already, but I am stuck at one point.

The source file looks like this:

dev1 size 1024
dev2 size 1024
dev3 size 1024
dev4 size 512
dev5 size 512

In the script the source file is the variable $INVFILE. Then I issue the command

cat $INVFILE | awk '{print $3}' | sort | uniq -c

Which gives the following output:

   3 1024
   2 512

I want to use this output in the following command, so that it uses the different sizes, and their counts (for this example I'm using the first line only, but in the script I want to use both lines in a sort of "for i in" function).

create dev count=3 size=1024MB

How can I do this in the script? And is there an easier way instead of the "for i in" function?

1
  • 1
    Note that awk can take a file as an argument, there is no need for cat there. You could just do awk '{print $3}' $INVFILE. This is what is known as a UUoC.
    – terdon
    Commented Jun 1, 2016 at 14:53

3 Answers 3

4

awk can do all the job.

try

awk '{ d[$3]++ ; } 
     END { for ( c in d ) 
        printf "create dev count=%d size=%dMB\n",d[c],c ;}' $INVFILE

and if it work :

awk '{ d[$3]++ ; } 
   END { for ( c in d ) 
         printf "create dev count=%d size=%dMB\n",d[c],c ;}' $INVFILE |
bash
3
  • +, but very complicated for a beginner...
    – gerhard d.
    Commented Jun 1, 2016 at 14:50
  • I agree. A very personnal point of view is to avoid useless pipe and multiple command. however the best command is the one you understand. (specially if you are the one responsible for it).
    – Archemar
    Commented Jun 1, 2016 at 14:52
  • @agc OK to break one line, but keep awk line in pattern { action} at least.
    – Archemar
    Commented Jun 1, 2016 at 20:45
0
awk '{print $3}' $INVFILE | sort | uniq -c | \
while read a b ; do \
    create dev count=$a size=${b}MB ; \
done

for only uses one list item per loop cycle, while read x_1 x_2 x_3... uses however many x_ns there are, (but never more items than happen to be in one line of the input file).

Note, if any of the input had more than two columns, change 'read a b' above to 'read a b c' -- the $c wouldn't be used in the loop, but it prevents read from assigning the rest of the line to $b.


The first line of pipes can be swapped out with datamash, with $a & $b swapped in the loop:

datamash -W -s -g3 count 3 < $INVFILE | \
while read a b ; do \
    create dev count=$b size=${a}MB ; \
done
3
  • Just to be sure. The while read function will run the command for every line in of the output? I will give it a try. Thanks!
    – Marty
    Commented Jun 1, 2016 at 14:36
  • Yes while read runs for every input line.
    – agc
    Commented Jun 1, 2016 at 15:19
  • This was excatly what I needed! Thanks all!
    – Marty
    Commented Jun 1, 2016 at 15:34
0

First of all, the 'uniq' - command has an option for ignoring n columns: '-f N'.

Afterwards you may put fields from an input into variables with 'read'.

So in total, the following command will pick the needed information from all lines of the input file:

cat input.txt | uniq -f2 -c | while read a b c d; do echo "command $a $d" ;done

Substitute "echo ..." with your command.

5
  • 1) Needs sort before uniq as per OP spec, (sorted by field yet). 2) Useless cat.
    – agc
    Commented Jun 1, 2016 at 15:28
  • @agc - isn't your answer using an equally useless cat ? Commented Jun 1, 2016 at 15:45
  • @don_crissti, : Yes, and with intent. It's the OP's useless cat, the goal being to ease the for vs while learning curve. OTOH gerhard d. is going for the full Monty with the most minimal command, so he should "put out the cat". I can revise my answer, (or add a minimalist addendum), but since it's gerhard's idea, he ought to have a few days dibs.
    – agc
    Commented Jun 1, 2016 at 16:15
  • @agc - you can't be serious ! Commented Jun 1, 2016 at 16:21
  • @don_crissti, lets focus on the code, not the coders.
    – agc
    Commented Jun 1, 2016 at 16:29

You must log in to answer this question.

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