#!/usr/bin/env perl use v5.36; use List::Util 'max'; my %price = ( 'Coca Cola' => 1.25, coke => 1.25, COLA => 1.25, Cola => 1.25, cola => 1.25, 'Pepsi Cola' => 1.25, pizza => 12.00, sandwich => 3.00, 'UNDEAD COLA' => undef, 'Undead Cola' => undef, 'Undead cola' => undef, 'undead cola' => undef, ); say 'Enter whole or partial name for key (just hit Return to exit).'; while (1) { print "\nName: "; my $name = ; chomp $name; unless (length $name) { say 'Exiting ...'; last; } unless ($name =~ /^[A-Za-z0-9 ]+$/) { say 'Only alphanumeric+space name searches allowed.'; next; } check_keys(\%price, $name); } sub check_keys ($hash, $name) { my %matches = map +($_ => 1), grep /$name/i, keys %$hash; if (keys %matches) { _printf_head($hash); if (exists $matches{$name}) { _printf($hash, 'EXACT', $name); delete $matches{$name}; } } else { say "No keys match '$name'."; return; } for (grep /^$name$/i, sort keys %matches) { _printf($hash, 'NO_CASE', $_); delete $matches{$_}; } for (sort keys %matches) { _printf($hash, 'PARTIAL', $_); } return; } sub _printf ($hash, $match, $key) { my $fmt = "%-7s %-@{[max map length, keys %$hash]}s "; $fmt .= defined $hash->{$key} ? "%.2f\n" : "%s\n"; printf $fmt, $match, $key, $hash->{$key} // ''; return; } sub _printf_head ($hash) { my $fmt = "%-7s %-@{[max map length, keys %$hash]}s %s\n"; printf $fmt, qw{Match Key Value}; printf $fmt, qw{----- --- -----}; return; } #### Enter whole or partial name for key (just hit Return to exit). Name: cok Match Key Value ----- --- ----- PARTIAL coke 1.25 Name: col Match Key Value ----- --- ----- PARTIAL COLA 1.25 PARTIAL Coca Cola 1.25 PARTIAL Cola 1.25 PARTIAL Pepsi Cola 1.25 PARTIAL UNDEAD COLA PARTIAL Undead Cola PARTIAL Undead cola PARTIAL cola 1.25 PARTIAL undead cola Name: Coca Cola Match Key Value ----- --- ----- EXACT Coca Cola 1.25 Name: Undead Cola Match Key Value ----- --- ----- EXACT Undead Cola NO_CASE UNDEAD COLA NO_CASE Undead cola NO_CASE undead cola Name: Cola Match Key Value ----- --- ----- EXACT Cola 1.25 NO_CASE COLA 1.25 NO_CASE cola 1.25 PARTIAL Coca Cola 1.25 PARTIAL Pepsi Cola 1.25 PARTIAL UNDEAD COLA PARTIAL Undead Cola PARTIAL Undead cola PARTIAL undead cola Name: cola Match Key Value ----- --- ----- EXACT cola 1.25 NO_CASE COLA 1.25 NO_CASE Cola 1.25 PARTIAL Coca Cola 1.25 PARTIAL Pepsi Cola 1.25 PARTIAL UNDEAD COLA PARTIAL Undead Cola PARTIAL Undead cola PARTIAL undead cola Name: ^cola$ Only alphanumeric+space name searches allowed. Name: (?{/path/to/evil_code}) Only alphanumeric+space name searches allowed. Name: Nightingale Tongues in Aspic No keys match 'Nightingale Tongues in Aspic'. Name: p Match Key Value ----- --- ----- PARTIAL Pepsi Cola 1.25 PARTIAL pizza 12.00 Name: s Match Key Value ----- --- ----- PARTIAL Pepsi Cola 1.25 PARTIAL sandwich 3.00 Name: Exiting ...