3

I want to reverse the uniq -c output from:

  1 hi
  2 test
  3 try

to:

hi
test  
test  
try  
try  
try

My solution now is to use a loop:

while read a b; do yes $b |head -n $a ;done <test.txt

I wonder if there are any simpler commands to achieve that?

Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
once
  • 1,369
  • 4
  • 22
  • 32

4 Answers4

3

another awk

awk '{while ($1--) print $2}' file
thanasisp
  • 5,855
  • 3
  • 14
  • 31
  • simplest solution by now, may i ask about '($1--)'? – once Jan 03 '18 at 01:47
  • 1
    this condition returns `$1` and decrease it by one. Similar to other languages that have the `++`,`--` operands, reduction happens after every evaluation. So it counts downwards from `$1` to zero, for every line. – thanasisp Jan 03 '18 at 11:03
2

Here's another solution

echo "\
1 hi
2 test
3 try" | awk '{for(i=1;i<=$1;i++){print($2)}}'

output

hi
test
test
try
try
try

This will work the same way, with

awk '{for(i=1;i<=$1;i++){print($2)}}' uniq_counts.txt

The core of the script, if of course

 { for (i=1;i<=$1;i++) { print $2 }

where awk has parsed the input into 2 fields, $1 being the number (1,2,3) and $2 is the value, (hi,test,try).

The condition i<=$1 tests that the counter i has not incremented beyond the count supplied in field $1, and the print $2 prints the value each time that i<=$1 condition is true.

IHTH

shellter
  • 36,525
  • 7
  • 83
  • 90
2

You don't need awk or any other command, you can do it entirely in bash

while read n s
do
    for ((i=0; i<n; i++))
    do
        echo $s;
    done
done < test.txt
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
2

Here my solution uses the bash brace expansion and the printf internal command.

while read a b
do
     eval printf "'%.${#b}s\n'" "'$b'"{1..$a}
done <test.txt

The following simple example

printf '%s\n' test{1..2}

prints two lines which contain the string test followed by a number:

test1
test2

but we can specify the exact number of characters to print by using the precision field of the printf command:

printf '%.4s\n' test{1..2}

to display:

test
test

The length of the characters to print is given by the length of the text to print (${#b}).

Finally the eval command must be used in other to use variables in the brace expansion.

Jdamian
  • 3,015
  • 2
  • 17
  • 22