Bad Matrix Reloaded
In an amusingly silly post, Aditya Athalye introduces us to two deliberately bad things that you didn’t know you wanted.
Bad Print
This consists of sending every character to its own print job, and then printing them as soon as the job finishes — who cares about ordering?
“Hmm, a couple of lines of Bash could do that”, I thought, and came up with this:
bad-print() (while IFS='\n' read -r -n1 c do printf "%s" "$c" & done <<< "$1"; echo) htdw() { bad-print "Hello there, dear world!" ;} htdw; htdw; htdw; htdw; htdw
Hello hter,e dear wrlod! Hello there, dea rworld! Helol hteer, dear worl!d Hello ther,e dear wodrl !Hell othere, drea worl!d
Looks pretty bad to me — which, considering the goal here, is good.
But this is just a warm-up for the next one.
Bad Matrix
Inspired by Bad Print, Aditya, in a fit of wild fancy (his words), wrote Bad Matrix. And you can promptly see that the results look just like Matrix digital rain not at all.
I was amused by the animation shown, so I tried to run the code — a single Bash function that delivers on its promise: the displayed effect is just as bad as advertized.
Now, the dollar-quoted stuff that shows up there, such as $'\235\246', is random, but the order of the kanji sequence isn’t — so I thought “hey, let’s change something to make this random as well”. Which I did.
Yet I seem to be incapable of restraining myself from tweaking other people’s Bash code when I put my hands on it. So there I go, renaming and regrouping things, and shuttling local functions out of the main one, and unbracing variables and compound commands, and adding arrays, and “hmm, I think this deserves to be a script instead of a single function”, and soon enough I have a whole file with another version of it — and then I might as well publish it, because people out there might really be in need of more Bad Matrices, and only a monster would hold back and deprive them of such basic necessities.
Therefore:
#!/usr/bin/env bash ## Bad Matrix Reloaded --- A still bad implementation of Matrix digital rain # SPDX-FileCopyrightText: © 2023 Aditya Athalye # SPDX-FileCopyrightText: © 2026 flandrew #---------------------# # Updated: 2026-04-20 # #---------------------# # Version: 0.2.0 # #---------------------# # SPDX-License-Identifier: GPL-3.0-or-later ## Commentary # # This is an intentionally bad implementation of Matrix digital rain. # https://en.wikipedia.org/wiki/Matrix_digital_rain # # "Bad" in the sense that the effect should look exactly like the original one # not at all — but with enough green dimmed Japanese stuff showing up that you # may perhaps be vaaaaguely reminded of the real thing. # # Aditya's original bad_matrix() function can be found here: # https://www.evalapply.org/posts/bad-matrix/index.html # # I (flandrew) pulled that function apart into this script; restructured and # simplified a few things; and further decomplected some internal functions. # # The only visible change for the user should be that the kanji selection is # now random (instead of always printing from the start: 日 一 大 年 中 会...) # I think this looks better, which means it's less bad — which may be worse. # But it still looks nearly as bad as before — which is most certainly good. # ############################################################################# #⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ ## Code ### Setup set -eo pipefail hash sed tput || exit 127 #⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ ### Variables cols=$(tput cols) rows=$(tput lines) # one hundred common kanji: ohck=(日 一 大 年 中 会 人 本 月 長 国 出 上 十 生 子 分 東 三 行 同 今 高 金 時 手 見 市 力 米 自 前 円 合 立 内 二 事 社 者 地 京 間 田 体 学 下 目 五 後 新 明 方 部 女 八 心 四 民 対 主 正 代 言 九 小 思 七 山 実 入 回 場 野 開 万 全 定 家 北 六 問 話 文 動 度 県 水 安 氏 和 政 保 表 道 相 意 発 不 党) #⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ ### Functions #### Main main() { cat /dev/urandom | print-line-fragment ;} print-line-fragment() while read -n "$((1 + RANDOM % cols))" line do sleep 0.5 maybe-goto-Y inject-matrix tput dim print-string-slowly "$line" & done #⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ #### Kanji inject-matrix() if ((RANDOM % 3 == 0)) then tput el else maybe-goto-Y color-me-matrix print-kanji fi print-kanji() for ((i=0; i++ < 1 + RANDOM % cols;)) do sleep 0.05 print-a-random-kanji & done print-a-random-kanji() { printf "%s " "${ohck[RANDOM % ${#ohck[@]}]}" ;} #⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ #### Slow-printing print-string-slowly() { <<<"$1" parse-chars | print-chars-slowly ;} parse-chars() { LANG="en_US.UTF-8" sed -E 's/(.)/\1\n/g' &} print-chars-slowly() while read char do printf "%q" "$char" | sed "s/''/ /g" & done #⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ #### Color color-me-matrix() { maybe-dim; tput setaf 2 ;} maybe-dim() if ((RANDOM % 3 == 0)) then tput dim else tput sgr0 fi #⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ #### Position maybe-goto-Y() if ((RANDOM % 2 == 0)) then tput cup "$((RANDOM % rows))" 0 fi #⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ ### Run it! main exit 0 # Local Variables: # coding: utf-8 # indent-tabs-mode: nil # sentence-end-double-space: nil # outline-regexp: "###* " # End: ## Bad Matrix Reloaded ends here
I thought about also changing something to make it rain from the top, instead of from the left; and that maybe we could replace the kanji with mirrored half-width kana. But better not: that would make it come dangerously close to the original, thereby running the risk of it actually looking good — which would be bad.
📆 2026-W17-1📆 2026-04-20