PHP String Functions in Bash: A Cheat Sheet
The index to the Bash function library: every PHP string function with its pure-Bash equivalent, short tested snippets, and when to use awk or sed instead.
~/ronggeng: a developer's notebook since 2009
PHP, Python and JavaScript, Linux and the command line, databases and the web, plus a long-running library of pure Bash functions named after their PHP counterparts. Every example is run before it is published.
The index to the Bash function library: every PHP string function with its pure-Bash equivalent, short tested snippets, and when to use awk or sed instead.
Writing Bash builtins in C: the .def format, compiling into bash vs enable -f, what my old awie-bash code got wrong, and a tested loadable port with timings.
Extra iptables matches and targets the kernel never shipped: country blocking with geoip, a TARPIT decoy port, port knocking, and the psd scan detector I ported.
Temp files and stale locks left behind by failed scripts are avoidable. Tested trap patterns for EXIT, INT, TERM and ERR, plus mkdir and flock locks.
One column for both address families: INET6_ATON() and INET6_NTOA(), IPv4-mapped addresses, correct sorting, indexed range queries and MariaDB's native INET6 type.
Export with WP-CLI, rebuild with a small Node script, keep every old URL working: what I learned relaunching this site as static HTML after dropping 1,600 posts.
PHP, Python, JavaScript and Git: language features and habits worth knowing.
Spread copies one level, the JSON trick breaks dates, maps and cycles, and structuredClone() fixes most of it. Tested examples, including what it...
Two small functions that stop search boxes and scroll handlers from running too often, with a runnable timeline that shows exactly when each one...
Why I convert os.system() calls to subprocess.run(): no shell injection, real exit codes, captured output, timeouts and input, with notes for Python...
?->, ?? and ??= all deal with null, but they solve different problems. Tested examples of each, short-circuiting, and the places where ?-> is not...
How I use python -m venv on servers and laptops: one environment per project, pinned requirements, no activation in cron, and why .venv never goes...
match looks like a shorter switch, but it compares strictly, never falls through, returns a value and throws when nothing matches. Here is what that...
Processes, services, networking and the tools you reach for every day.
Extra iptables matches and targets the kernel never shipped: country blocking with geoip, a TARPIT decoy port, port knocking, and the psd scan...
One missing slash nests a directory. One empty source wipes a backup. Tested rsync recipes for mirroring, filtering, verifying and copying over SSH.
Why a volume shows the image's files and a bind mount hides them, and how a root container leaves files your own user cannot edit or delete. Four...
Cron loses output, overlaps jobs and skips runs while the machine is off. systemd timers fix all three. A tested walk-through with OnCalendar...
The same 147 kB binary in a 257 MB image or an 8.44 MB one. Multi-stage builds, named stages, a --target debug image, and why build secrets still...
A one-line code change should not reinstall every dependency. Timed rebuilds show how instruction order, .dockerignore and ARG placement decide what...
HTTP, caching, redirects and running sites without surprises.
Export with WP-CLI, rebuild with a small Node script, keep every old URL working: what I learned relaunching this site as static HTML after dropping...
A persistent WordPress object cache for hosting without Redis: each entry is a PHP file that OPcache keeps compiled. How it works, and what it did on...
What the backend really receives behind nginx: proxy_pass URI rewriting, Host and X-Forwarded headers, WebSocket upgrades, 504s from timeouts, and...
Not first match, not longest match, but a mix of both. A test config where every location names itself shows exactly how nginx picks one, and where...
try_files checks files in order and only the last argument redirects. Static clean URLs, a PHP front controller with php-fpm, and the upload exploit...
no-cache does not mean do not cache. A hands-on look at Cache-Control, ETags and 304 responses with a tiny Node server, plus how a CDN treats them.
Stored functions, data types and queries for real data.
One column for both address families: INET6_ATON() and INET6_NTOA(), IPv4-mapped addresses, correct sorting, indexed range queries and MariaDB's...
Store IPv4 addresses as INT UNSIGNED and test CIDR membership with a bitmask or, much faster on a big table, an indexed BETWEEN range on network and...
Network, Broadcast and Prefix From a Netmask
Work out the network, broadcast address and prefix length of an IPv4 address inside a query, using INET_ATON(), INET_NTOA() and a little bitwise...
Series
Started in 2009: small shell functions named after their PHP counterparts (__pgrepf(), _execq(), basename(), dirname(), emptydir(), explode() and implode() and more), each rewritten, tested and explained.
Length, case, search, replace, pad and trim, the way PHP names them.
Split and Join Strings
PHP's explode() and implode() in Bash: read -ra and mapfile -d for splitting, "${arr[*]}" for joining, and functions that cope with multi-character...
Lowercase the First Character
lcfirst() in Bash with ${var,} and a Bash 3.2 fallback, used for PascalCase to camelCase, plus a fix for names that begin with an acronym.
Remove a Substring From a String
Delete every occurrence of a substring with one Bash parameter expansion, no sed or tr needed, and the quoting mistakes that make it go wrong.
Pad a String to a Fixed Length
PHP-compatible str_pad() in pure Bash, when printf "%-10s" and %05d are enough, and why multibyte text breaks the alignment of your columns.
Repeat a String N Times
A str_repeat() for Bash that stays fast at millions of copies, why the common printf trick slows down, and the two bugs in the 2009 version.
Replace Text in a String
Replace text in a Bash string without sed: ${s//search/replace}, anchored replacements, why you must quote the search, and what Bash 5.2 did to &.
Case-Insensitive Substring Search
Check whether a string contains a substring regardless of case, with a Bash 4 version, a Bash 3.2 fallback using nocasematch, and a PHP-style...
Get the Length of a String
Bash's ${#var} counts characters, PHP's strlen() counts bytes. A clean strlen() function, a strbytes() companion, and the locale traps in between.
Check if a String Contains a Substring
Test whether a string contains a substring in pure Bash, or get the rest of the string from the first match the way PHP's strstr() does.
Convert a String to Lowercase
A strtolower() for Bash 4 and the stock macOS Bash 3.2, why ${var,,} depends on your locale, and when declare -l, tr, awk or nocasematch fit better.
Convert a String to Uppercase
A strtoupper() that works on Bash 4+ and macOS's Bash 3.2, plus ${var^^pattern} for uppercasing only some characters and declare -u for variables.
Strip Leading and Trailing Whitespace
PHP-style trim(), ltrim() and rtrim() in pure Bash with parameter expansion, plus why the popular read trick quietly removes your backslashes.
Uppercase the First Character
A ucfirst() for Bash 4+ and macOS's Bash 3.2, what "first character" really means, and how to get "Hello" from "hELLO" or " hello".
Capitalise Every Word in a String
A ucwords() for Bash that works word by word instead of char by char, preserves all whitespace, and lets you decide what counts as a word boundary.
Writing Bash builtins in C: the .def format, compiling into bash vs enable -f, what my old awie-bash code got wrong, and a tested loadable port with...
Split, join, look up and validate what your script is given.
Check if an Array Contains a Value
A correct in_array() for Bash, an associative-array set for many lookups, and a demonstration of why [[ "${arr[*]}" =~ value ]] gives false positives.
Check if a Value Is a Number
Check that input is a whole number, a signed integer or a decimal before doing arithmetic, and avoid the octal, empty-string and injection problems...
Ask a Yes/No Question Safely
A yes/no confirmation prompt for Bash scripts that accepts any case, has an optional default and handles cron, pipes and EOF without looping forever.
A tested getopts skeleton for Bash scripts: flags, options with values, required options, error handling, and a manual loop for --long options.
while IFS= read -r line is the correct loop, but the last line, pipes, commands that read stdin and Windows line endings each have a trap. Here they...
File names, directories and running programs without forking.
pgrep -f Using Only /proc
Find processes by their full command line in pure Bash by reading /proc/PID/cmdline, with the NUL bytes handled properly and the 2009 bugs fixed.
Run a Command Quietly and Keep Its Status
Run a command silently and test only its exit status. Why "$@" beats storing a command in a string, and what to use for pipelines.
Strip the Directory From a Path
Get the file name from a path with parameter expansion, matching coreutils basename on trailing slashes, "/" and suffixes, without starting a process.
Get the Directory Part of a Path
Get the directory part of a path in pure Bash, matching coreutils dirname on trailing slashes, bare names and the root, without starting a process.
Check Whether a Directory Is Empty
Test whether a directory is empty in pure Bash with nullglob and dotglob, handle hidden and unreadable directories, and know when find -quit is...
Temp files and stale locks left behind by failed scripts are avoidable. Tested trap patterns for EXIT, INT, TERM and ERR, plus mkdir and flock locks.
Strict mode, option parsing, cleanup and error handling.
set -euo pipefail is good advice, but each option has rules about when it fires. Here is what each one does and the cases that surprise people.