0

Using the awk command, I am to display lines 3-5 backwards of a file i have created and before the outputted line, the line number is to be displayed (i.e. line 3:). I am also to display the total wordcount of all three lines. My code is provided below. I keep obtaining an error message for the '%s' and not sure where to go from here, any help?

BEGIN { print("<< Start of file >>"); }

NR>=3 && NR<=5 { for (i = NF; i >= 1; i--)

                printf "%d: %s ", $i;
                print ""
                wordCount += NF;


}



END { printf "<< End of file: wordCount = %d >>\n", wordCount }

Here's the input file:

Gimme presents I want more!
Gimme presents, I did my chores!
A bicycle, a tricycle, a motor vehicle!
I deserve it, you reverse it!
Gimme presents; more, more, more
Gimme presents I need more!

And the out put i obtain is:

(FILENAME=presents FNR=3) fatal: not enough arguments to satisfy format string
        `%d: %s '
             ^ ran out for this one
4
  • 3
    Can you post example of your input and desired output ? Feb 9, 2018 at 0:11
  • Also, you mentioned error for %s. Please post the exact text of error that you're getting. Feb 9, 2018 at 0:13
  • it has been updated, sorry for the confusion!
    – Herman
    Feb 9, 2018 at 0:16
  • 1
    Aha, I see the issue. printf "%d: %s ", $i; The %d matches for $i but there's nothing you provide to match for %s. I'll put it in an answer shortly Feb 9, 2018 at 0:17

1 Answer 1

1

Code bug portion

Key issue is that you have %d: %s format, but there's only one argument $i to match the format speficiers, i.e. $i matches with %d but not with %s.

Once you change the script as so:

#!/usr/bin/awk -f

BEGIN { print("<< Start of file >>"); }

NR>=3 && NR<=5 { 
    for (i = NF; i >= 1; i--)
        printf "%d: %s ", i,$i;
    print ""
    wordCount += NF;


}

END { printf "<< End of file: wordCount = %d >>\n", wordCount }

Then there's no error, and produces output as so:

$ ./awk_script.awk input.txt
<< Start of file >>
7: vehicle! 6: motor 5: a 4: tricycle, 3: a 2: bicycle, 1: A 
6: it! 5: reverse 4: you 3: it, 2: deserve 1: I 
5: more 4: more, 3: more, 2: presents; 1: Gimme 
<< End of file: wordCount = 18 >>

Fixing code to match desired behavior

However, your description was:

I am to display lines 3-5 backwards of a file i have created and before the outputted line, the line number is to be displayed (i.e. line 3:)

That means before processing each field using for-loop, you need to output line number first:

#!/usr/bin/awk -f

BEGIN { print("<< Start of file >>"); }

NR>=3 && NR<=5 {
    printf "line %d:",NR; # display line number first
    for (i = NF; i >= 1; i--)
        printf " %s ", $i;
    print ""; 
    wordCount += NF;

}

END { printf "<< End of file: wordCount = %d >>\n", wordCount }

Which works as so:

$ ./awk_script.awk input.txt
<< Start of file >>
line 3: vehicle!  motor  a  tricycle,  a  bicycle,  A 
line 4: it!  reverse  you  it,  deserve  I 
line 5: more  more,  more,  presents;  Gimme 
<< End of file: wordCount = 18 >>
8
  • Wow! such a simple fix, upvote! One more thing, how would we rid the text from repeating itself with the original pattern, as it is appended to the reversed line in the output?
    – Herman
    Feb 9, 2018 at 0:36
  • I figured it out, had to remove the 'print;' line!
    – Herman
    Feb 9, 2018 at 0:46
  • Oops, sorry, the print "" was necessary. Occasionally small details like that escape my attention :) Feb 9, 2018 at 0:49
  • It looks like you're just using print "" in order to tack on a newline. How about just adding \n to the end of the printf format argument instead? @HermanTravis
    – Wildcard
    Feb 9, 2018 at 1:01
  • 1
    @Wildcard That's of course if you're talking about changing printf " %s ", $i; into printf " %s \n", $i;. Remember that the printf part is inside for loop. If you mean printf "\n" after (!) the for loop, then it's OK Feb 9, 2018 at 1:05

You must log in to answer this question.

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