Perl: Nested subroutines

Perl doesn't support nested sub-routines natively, but you can fake them by using functions defined at runtime.

sub a {
    local *b = sub {
        return 123;

    return b();  # Works as expected

b();  # Error: "Undefined subroutine &main::b called at ..."

Some times nested functions can be useful for simplifying readability of code while also allowing simple copy/paste for code re-use.

Leave A Reply

Books of 2021

List of books I read in 2021. Also see the list of 2020. The date indicated denotes the date I started reading the book.

2021-01-01 - Ready Player Two - 366 pages
2021-01-06 - The Institute - 561 pages
2021-01-14 - Turtles All the Way Down - 286 pages
2021-01-19 - Mindfulness In Plain English - 196 pages
2021-01-22 - Catcher In the Rye - 214 pages

Leave A Reply

Proxmox: Disable registration popup for 6.3

To disable the registration popup on Proxmox 6.3 run the following command:

perl -0777 -pi -E 's/if \(res === null \|.*?\) \{/if (false) {/s' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
Leave A Reply - 1 Reply

Perl: Slurp entire file in a one liner

I need to change some text in a file that's spread across multiple lines. This means perl -pE won't work because it treats each line as a separate regexp. Reading the file in to one big string and then running a multiline regexp is the best solution.

Using -0777 tells Perl to read the entire file in to one string and allows multi-line regexps to work as intended.

If you have an input file with the content like:

if (foo
    && bar && !true) {
    # Do stuff

You can change the if statement with a one-liner like this:

perl -0777 -pE 's/\(foo.*?\)/(test)/s' /tmp/input.txt
Leave A Reply

Eagleson's law

“Any code of your own that you haven't looked at for six or more months might as well have been written by someone else.” - Eagleson's Law

Seems about right.

Leave A Reply

Bash: Using previous command's parameters

Bash allows you to save some typing by referencing the previous command's parameters via a variable. If you want to reference the first parameter from the previous command you would use !^ and if you want the last parameter you would use !$. A real world example would be something like this:

mkdir /long/dir/structure/new_dir
cd !$

This would make a new directory and then change to that directory. Alternately you can reference numbered parameters using !:2 to reference the 2nd parameter.

Leave A Reply

Apache: Blocking access to certain file types with .htaccess

My templating system uses .stpl files for it's definitions. I do not want to serve these files directly to my users so I used an .htaccess file to block them.

<Files ~ "\.stpl$">
    Order allow,deny
    Deny from all
Leave A Reply

PHP: Look in to a multi-dimensional array using array_dive()

I have a multi-dimensional array that I need to extract data from. Given a string in the format of "person.first" I want to descend in to the array looking for person -> first. I wrote this array_dive() function to facilitate this lookup.

function array_dive(string $needle, array $haystack) {
    // Split at the periods
    $parts = explode(".", $needle);

    // Loop through each level of the hash looking for elem
    $arr = $haystack;
    foreach ($parts as $elem) {
        //print "Diving for $elem<br />";
        $arr = $arr[$elem] ?? null;

        // If we don't find anything stop looking
        if ($arr === null) {

    // If we find a scalar it's the end of the line, anything else is just
    // another branch, so it doesn't cound as finding something
    if (is_scalar($arr)) {
        $ret = $arr;
    } else {
        $ret = null;

    return $ret;

Here is a sample script that shows the function in action.

Leave A Reply

Smarty: E_NOTICE warnings on undefined template variables

After upgrading my PHP and Smarty installations I started getting E_NOTICE warnings for any template variable that was not defined. There are valid reasons to have an undefined variable in your template, so I did not want to show a notice every time one is encountered. A real world example that I've encountered is:

{if $debug}
    Debug: {$error_string}

One could argue you could just test if $debug is non-empty, but that's more typing and feels redundant. I have a lot of old templates using this sysntax and didn't want to have to update all of them. The simple solution I found in the Smarty README.

// Don't show missing template variables as E_NOTICE
$smarty->error_reporting = E_ALL & ~E_NOTICE;

Note: This does not mask your normal PHP E_NOTICE errors, just ones generated by Smarty.

Leave A Reply

Perl: Named captures in regexps

In a regular expression you can capture strings into variables using the default syntax:

$str = "2020-05-20";
$str =~ m/(\d{4})-(\d{2})-(\d{2})/;

printf("Year: %s Month: %s Day: %s\n", $1, $2, $3);

In a more complex regular expression/string things may move around. In this case it's better to use named captures instead of numeric captures. This can be done by using the (?<name>) syntax. This will capture that parenthesis pair in to the hash %+ with the name specified.

$str = "2020-05-20";
$str =~ m/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

printf("Year: %s Month: %s Day: %s\n", $+{year},$+{month},$+{day});

Using named captures you can easily update your regular expression if the position of elements in your string change.

Note: If you use named captures, Perl also populates the numeric equivalent.

Leave A Reply

Adjective and animal lists

For a personal project I wanted to generate AdjectiveAnimal pairs. This required me to find a list of animal names and adjectives. This was not a trivial endeavor and required me to find, clean up, and organize several lists.

Feel free to borrow my lists if you want to save yourself a headache. Using these lists I can generate pairs like: PracticalOsprey, HumorousTermite, and DiplomaticTarpon.

I also wrote a tool to generate pairs based on these two lists.

Leave A Reply

Perl: Time::Piece

Perl has a great core module for dealing with dates and times: Time::Piece.

use Time::Piece;

my $t = localtime();

my $unixtime = $t->epoch(); # Unixtime
my $human    = $t->cdate(); # Human readable

# Format a date/time for output
print $t->strftime("%Y-%M-%d") . "\n";

# Convert a specific format to a date/time object
my $bd = localtime->strptime("1985-02-14", "%Y-%M-%d");
print "You were born on a " . $bd->fullday . " in " . $bd->year . "\n";

# Date/Time addition
print "In one hour it will be: " . (localtime() + 3600)->hms . "\n";

It works by overriding the built in localtime() and gmtime() functions and giving them an object oriented interface. I highly recommend looking at it if you have to deal with dates and times.

Leave A Reply

C/C++: Force floating point math

In C/C++ if you want to get a floating point result from integer division you need to cast at least one of the values as a float to force floating point division (not integer):

int a = 1;
int b = 7;

float c = (float)a / b;

If you don't cast one of the variables as a float you will get an integer result. This is true even if your resulting variable is cast as a float.

Leave A Reply

Tasmota API via HTTP using Curl

Tasmota has a huge catalog of commands that can be run via the serial console, MQTT, or HTTP. These commands are great for scripting purposes. The easiest way I've found to send a command is with Curl.


The API will answer in JSON which is easily digestible with JQ.

curl -s | jq
Leave A Reply

Espressif WiFi MCU cost comparison

Espressif has just released their newest WiFi enabled MCU the ESP32-S2. It's a successor to the ESP8266 and has many improvements. Not only does it have more CPU, more memory, and more GPIO pins it's also cheaper. Just for posterity's sake here is the current cost for of WiFi enabled MCUs.

MCU Cost
ESP8266 $1.60
ESP8285 $1.05
ESP32 (gen 1) $3.00
ESP32 (gen 3) $1.50
ESP32-S2 $0.99

Note: This is the cost for the bare IC only.

Leave A Reply