• $ cat "

    Linux Kata #2: Ordering Lunch

    "

    This is a kata with a couple of different difficulty levels.

    Level 1:

    Count how many attendees what chicken for lunch and how many want tofu. It's OK to run two separate commands to get the counts.

    Here is the file contents of the file food.txt. It's worth noting that the file contains a mix of spaces and tabs as column separators.

    Name                	Attendance        	Response    Food
    Allen Key Meeting Organizer None Chicken
    Bob Sled Required Attendee Accepted Tofu
    Clay Pigeon Required Attendee Accepted Chicken
    Cliff Edge Required Attendee Accepted Tofu
    Guy Ropes Required Attendee Accepted Tofu
    Jack Hammer Required Attendee Accepted Chicken
    Jerry Cann Required Attendee Declined
    Jim Boot Required Attendee Accepted Chicken
    Jim Equipment Required Attendee Accepted Chicken
    Jock Strap Required Attendee Accepted Tofu
    Lou Paper Required Attendee Accepted Chicken
    Mike Stand Required Attendee Declined
    Morris Minor Required Attendee Accepted Chicken
    Phillip Screwdriver Required Attendee Accepted Chicken
    Ray Gunn Required Attendee Accepted Tofu
    Roman Bath Required Attendee Accepted Tofu
    Stanley Knife Required Attendee Accepted Chicken
    Terry Towelling Required Attendee Accepted Tofu
    Walter Closet Required Attendee Accepted Chicken
    Catherine Wheel Required Attendee Declined Chicken
    Joy Stick Required Attendee Accepted Tofu
    Kitty Litter Required Attendee Accepted Tofu
    Pearl Necklace Required Attendee Accepted Tofu
    Penny Farthing Required Attendee Declined Chicken
    Jim Nazium Required Attendee Declined

    Level 2:

    Same task as level 1, but the result from your command/script should be a single line with the format "Tofu: 10, Chicken: 12"


    Level 3:

    Same task as level 2, but the lunch options may consist of multiple words.

    Here's the file contents of the file food2.txt. There's a mix of spaces and tabs in this file as well.

    Name                	Attendance        	Response    Food
    Allen Key Meeting Organizer None Chicken
    Bob Sled Required Attendee Accepted Fried tofu
    Clay Pigeon Required Attendee Accepted Chicken
    Cliff Edge Required Attendee Accepted Fried tofu
    Guy Ropes Required Attendee Accepted Fried tofu
    Jack Hammer Required Attendee Accepted Chicken
    Jerry Cann Required Attendee Declined
    Jim Boot Required Attendee Accepted Chicken
    Jim Equipment Required Attendee Accepted Chicken
    Jock Strap Required Attendee Accepted Fried tofu
    Lou Paper Required Attendee Accepted Chicken
    Mike Stand Required Attendee Declined
    Morris Minor Required Attendee Accepted Chicken
    Phillip Screwdriver Required Attendee Accepted Chicken
    Ray Gunn Required Attendee Accepted Fried tofu
    Roman Bath Required Attendee Accepted Fried tofu
    Stanley Knife Required Attendee Accepted Chicken
    Terry Towelling Required Attendee Accepted Fried tofu
    Walter Closet Required Attendee Accepted Chicken
    Catherine Wheel Required Attendee Declined Chicken
    Joy Stick Required Attendee Accepted Fried tofu
    Kitty Litter Required Attendee Accepted Fried tofu
    Pearl Necklace Required Attendee Accepted Fried tofu
    Penny Farthing Required Attendee Declined Chicken
    Jim Nazium Required Attendee Declined

    The output should still be "Tofu: 10, Chicken: 12".


    Suggested solution for level 1:

    cat food.txt | grep Tofu | wc -l;cat food.txt | grep Chicken | wc -l

    These commands basicly just lists the entire file contents, filters out all lines containing the word Tofu/Chicken and then counts the number of filtered lines.


    Suggested solution for level 2:

    awk '{if ($NF == "Tofu") tofu_count += 1; else if ($NF == "Chicken") chicken_count += 1 } END {print "Tofu: ",tofu_count,", Chicken: ",chicken_count}' food.txt

    This AWK program matches has no filtering condition, so it matches all lines. For each line which has Tofu/Chicken as the last word it increments the corresponding variable. When all lines have been processed it outputs the values in the variables and some additional text. NF is a magical variable containing the number of fields in a record. $ is used to extract a field with a given 1-based index. So $NF evaluates to the last word on a given line.


    Suggested solution for level 3:

    awk 'BEGIN {FS = " {2,}|\t+"}{if ($NF == "Fried tofu") tofu_count += 1; else if ($NF == "Chicken") chicken_count += 1} END {print "Tofu: ",tofu_count,", Chicken: ",chicken_count}' food2.txt
    Tofu: 10 , Chicken: 12

    Most of the script is the same as in the solution for the level 2 problem. However, in this script the field separator has been customized so that words separated by a single space are considered to be part of the same field. The FS variable contains the field separator expression, which in this case is a regular expression which matches 2 or more spaces or 1 or more tabs.