SlideShare a Scribd company logo
1 of 73
Download to read offline
Don’t BASH your head in:
Rx for shell variables.
Steven Lembark
Workhorse Computing
lembark@wrkhors.com
Quick review
BASH is interpreted.
Loops are re-parsed.
Variables can appear anywhere.
Unlike Perl, Python, Ruby, Go, Haskell, Scala, Scheme,
Which separate statements from var’s.
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
foo=”$files”; interpolated value of files.
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
foo=”$files”; interpolated value of files.
foo=$(ls $files); command output.
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
foo=”$files”; interpolated value of files.
foo=$(ls $files); command output.
foo=”$(ls $files)”; string with listing of files.
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
foo=”$files”; interpolated value of files.
foo=$(ls $files); command output.
Most of the work is interpolating:
echo “Your files are: $(ls $somedir)”;
De-mangling variable names
> foo=’bar’;
> echo “foo$foo”; ”foobar”
> echo “$bar_foo”; “”
Oops: Variable “bar_foo” doesn’t exist.
De-mangling variable names
> foo=’bar’;
> echo “foo$foo”; ”foobar”
> echo “$bar_foo”; “”
Isolate ‘foo’ as variable name:
“${foo}_bar # “bar_bar”
Variable commands
cmd=’/bin/ls’;
arg=’-lt’;
Variable commands
cmd=’/bin/ls’;
arg=’-lt’;
files=$($cmd $arg $1); /bin/ls -lt ...
Variable commands
# interpolate each command into the loop
for i in $cmd1 $cmd2 $cmd3
do
$i $args;
done
Really anywhere!
foo=’bar’;
Really, anywhere!
foo=’bar’;
$foo=’blort’;
Q: What happens?
Really, anywhere!
foo=’bar’;
$foo=’blort’;
Q: What happens?
A: Nada.
bash: bar=blort: command not found
Your one chance at success
BASH parses in two phases:
Lexical substitution & tokenizing.
Execution.
Variables have to expand on the first pass to be used.
“foo=blort” cannot be executed, so it failed.
A second chance in life
‘eval’ adds one cycle.
Interpolates variables.
Passes result to the shell.
‘++’ is two levels deep.
> eval"$foo=blort";
+ eval bar=blort
++ bar=blort
> echo $bar;
+ echo blort
blort
Or a third chance...
eval “eval … “;
Work out what is happening:
a=’$HOME/?.*’;
b=’foo’;
c=eval “eval $a $b”’;
Verbosity & Execution
See what bash is doing with the variables:
> set -vx;
Verbosity & Execution
See what bash is doing with the variables:
> set -vx;
echo -ne "033]0;./$(basename $PWD) 007"
+++ basename
/sandbox/lembark/writings/RockfordLUG/bash
++ echo -ne '033]0;./bash 007'
>
Verbosity & Execution
See what bash is doing with the variables:
> set -vx;
echo -ne "033]0;./$(basename $PWD) 007"
+++ basename
/sandbox/lembark/writings/RockfordLUG/bash
++ echo -ne '033]0;./bash 007'
>
“unset” removes variables
> unset PROMPT_COMMAND;
> set -vx;
>
Or set verbosity in the script
#!/bin/bash -vx
…
or localize the verbosity:
set -vx;
do something
set -;
Verbosity & Execution
> unset PROMPT_COMMAND;
> set -vx;
> foo=bar; what I typed
foo=bar; what BASH read
+ foo=bar single ‘+’is one level deep
Verbosity & Execution
> unset PROMPT_COMMAND;
> set -vx;
> foo=bar; what I typed
foo=bar; what BASH read
+ foo=bar single ‘+’is one level deep
> $foo='blort';
>foo='blort';
+ bar=blort no second chance to re-parse
Verbosity & Execution
> unset PROMPT_COMMAND;
> set -vx;
> foo=bar; what I typed
foo=bar; what BASH read
+ foo=bar single ‘+’is one level deep
> $foo='blort';
>foo='blort';
+ bar=blort no second chance to re-parse
bash: bar=blort: command not found
Why use ‘-vx’?
-v alone is useful sometimes.
-x alone usually isn’t.
Example: Hidden disk hogs
#!/bin/bash
dirs="/home/$(whoami)/.*";
cmd="du -msx $dirs | sort -rn | head -3";
eval "$cmd";
Buggy hogs
$ ./y
1232 /home/lembark/.
0 /home/lembark/..
Add verbosity
#!/bin/bash
set -vx;
dirs="/home/$(whoami)/.*";
cmd="du -msx $dirs | sort -rn | head -3";
eval "$cmd";
Shows the bug: . & ..
$ ./y
dirs="/home/$(whoami)/.*";
++ whoami
+ dirs='/home/lembark/.*'
cmd="du -msx $dirs | sort -rn | head -3";
+ cmd='du -msx /home/lembark/.* | sort -rn | head -3'
eval "$cmd";
+ eval 'du -msx /home/lembark/.* | sort -rn | head -3'
du -msx /home/lembark/.* | sort -rn | head -3
++ sort -rn
++ head -3
++ du -msx /home/lembark/. /home/lembark/..
/home/lembark/.aceinnovative /home/lembark/.adobe <snip>
1232 /home/lembark/.
0 /home/lembark/..
Fix: Add a letter
#!/bin/bash
set -vx;
dirs="/home/$(whoami)/.[a-z]*";
cmd="du -msx $dirs | sort -rn | head -3";
eval "$cmd";
Start with the right dirs
$ ./y
dirs="/home/$(whoami)/.[a-z]*";
++ whoami
+ dirs='/home/lembark/.[a-z]*'
cmd="du -msx $dirs | sort -rn | head -3";
+ cmd='du -msx /home/lembark/.[a-z]* | sort -rn | head -3'
eval "$cmd";
+ eval 'du -msx /home/lembark/.[a-z]* | sort -rn | head -3'
du -msx /home/lembark/.[a-z]* | sort -rn | head -3
++ sort -rn
++ head -3
++ du -msx /home/lembark/.aceinnovative /home/lembark/.adobe
<snip>
270 /home/lembark/.openoffice
244 /home/lembark/.mozilla
193 /home/lembark/.config
Compare: Only “-v”
$ ./y
dirs="/home/$(whoami)/.[a-z]*";
cmd="du -msx $dirs | sort -rn | head -3";
eval "$cmd";
du -msx /home/lembark/.[a-z]* | sort -rn | head -3
270 /home/lembark/.openoffice
244 /home/lembark/.mozilla
193 /home/lembark/.config
Compare: Only “-x”
$ ./y
++ whoami
+ dirs='/home/lembark/.[a-z]*'
+ cmd='du -msx /home/lembark/.[a-z]* | sort -rn | head -3'
+ eval 'du -msx /home/lembark/.[a-z]* | sort -rn | head -3'
++ sort -rn
++ head -3
++ du -msx /home/lembark/.aceinnovative /home/lembark/.adobe
<snip>
270 /home/lembark/.openoffice
244 /home/lembark/.mozilla
193 /home/lembark/.config
Command execution
We all remember backticks:
a=`ls -al ~`’;
Command execution
We all remember backticks:
a=`ls -al ~`’;
Better off forgotten:
No way to nest them for one.
Hard to read for another.
Command execution
BASH offers a better way:
$( ... )
i.e., “interpolate subshell output”.
Output of arbitrary commands:
files=$(ls ~);
jobs=$( grep ‘MHz’ /proc/cpuinfo | wc -l );
echo -e “DiskHogz:n$(du -msx *|sort -rn|head)”;
Twisting a path with basename
basename
locates
input for
next step.
cmd=’/image/bin/extract-hi-res’;
dir=’../raw’;
cd high-res || exit -1;
for i in ../low-res/culled/*;
do
echo “Input: ‘$i’”;
$cmd $dir/$(basename $i .ppm).nef;
done
Twisting a path with basename
Quotes
hilite
whitespace
in $1.
Don’t
leave
home
without
them...
cmd=’/image/bin/extract-hi-res’;
dir=’../raw’;
cd high-res || exit -1;
for i in ../low-res/culled/*;
do
echo “Input: ‘$i’”;
$cmd $dir/$(basename $i .ppm).nef;
done
Being there
A “here script” is “appended from stdin”.
Double-quotish.
> perl -MCPAN -E shell <<CPAN 2>&1 | tee a;
upgrade
install Module::FromPerlVer
q
CPAN
Being there
A “here script” is “appended from stdin”.
Double-quotish, into stdin.
> perl -MCPAN -E shell <<CPAN 2>&1 | tee a;
upgrade
install Module::FromPerlVer
q
CPAN
Being there
Closing tag sends EOF (^D) to command:
> perl -MCPAN -E shell <<CPAN 2>&1 | tee a;
upgrade
install Module::FromPerlVer
CPAN
Being there
module=’Module::FromPerlVer’;
> perl -MCPAN -E shell <<CPAN 2>&1 | tee a;
upgrade
install $module
CPAN
Being there
#!/bin/bash
...
path=”$mysql_d/$tspace”;
mkdir -p $path || exit -2;
mysql -U$user -P$pass <<SQL || exit -3;
create tablespace $tspace
using ‘$path’ … ;
create table big ( … ) tablespace $tspace;
SQL
Being there
mysql -U$user -P$pass <<SQL || exit -3;
create tablespace $tspace
using ‘$path’ … ;
create table
$(cat $table-1.sql)
tablespace $tspace;
SQL
Slicing with curlies
Remove strings from the head or tail of a string.
${i#glob} ${i%glob}
${i##glob} ${i%%glob}
Slicing with curlies
Slice the head:
${i#glob}
${i##glob}
# is shortest match
## is longest match
Slicing with curlies
Slice the tail:
${i%glob}
${i%%glob}
% is shortest match
%% is longest match
Stripping a prefix.
Say you want to prefix ‘/opt/bin’ onto a PATH.
But it may already be there.
You don’t know if someone else hacked the path.
Q: How can we put ‘/opt/bin’ at the front, once?
Stripping a prefix.
Say you want to prefix ‘/opt/bin’ onto a PATH.
But it may already be there.
You don’t know if someone else hacked the path.
Q: How can we put ‘/opt/bin’ at the front, once?
A: Take it off each time.
Striptease.
‘#’ strips off leading content.
Say we tried this:
PATH=”/opt/bin:${PATH#/opt/bin:}”;
OK, I can run it a hundred times.
Path hack striptease.
‘#’ strips off leading content.
Say we tried this:
PATH=”/opt/bin:${PATH#/opt/bin:}”;
OK, I can run it a hundred times.
Until /opt/bin isn’t first:
“~/bin:/opt/bin: ...”
Globs save the day
Find everything up to the first match:
PATH=”/opt/bin:${PATH#*/opt/bin:}”;
> echo $PATH;
/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/
i486-pc-linux-gnu/gcc-bin/4.1.2
Globs save the day
Find everything up to the first match:
PATH=”/opt/bin:${PATH#*/opt/bin:}”;
> echo ${PATH#*/opt/bin:};
+ echo /usr/local/bin:/usr/bin:/bin:/opt/bin:/
usr/i486-pc-linux-gnu/gcc-bin/4.1.2
Globs save the day
Find everything up to the first match:
PATH=”/opt/bin:${PATH#*/opt/bin:}”;
> echo ${PATH#*/opt/bin:};
+ echo /usr/local/bin:/usr/bin:/bin:/opt/bin:/
usr/i486-pc-linux-gnu/gcc-bin/4.1.2
Globs save the day
Find everything up to the first match:
PATH=”/opt/bin:${PATH#*/opt/bin:}”;
/usr/i486-pc-linux-gnu/gcc-bin/4.1.2
Fixing the path
Takes a bit more logic:
Strip /opt/bin out of the path.
Paste it onto the front.
Globs aren’t smart enough.
Fixing the path
Takes a bit more logic:
First break up the path.
> echo $PATH | tr ':' "n"
/opt/bin
/usr/local/bin
/usr/bin
/opt/bin
/bin
/usr/i486-pc-linux-gnu/gcc-bin/4.1.2
Fixing the path
Takes a bit more logic:
Then remove ‘/opt/bin’.
> echo $PATH | tr ':' "n" | grep -v '/opt/bin'
/usr/local/bin
/usr/bin
/bin
/usr/i486-pc-linux-gnu/gcc-bin/4.1.2
Fixing the path
Takes a bit more logic:
Recombine them.
> a=$(echo $PATH | tr ':' "n" |
grep -v '/opt/bin' | tr "n" ':');
> echo $a
/usr/local/bin:/usr/bin:/bin:/usr/i486-pc-linux-
gnu/gcc-bin/4.1.2::
Fixing the path
Takes a bit more logic:
Prefix ‘/opt/bin’.
> a=$(echo $PATH | tr ':' "n" |
grep -v '/opt/bin' | tr "n" ':');
> echo “/opt/bin:$a”;
/opt/bin:/usr/local/bin:/usr/bin:/bin:/usr/i486-
pc-linux-gnu/gcc-bin/4.1.2::
Fixing the path
Takes a bit more logic:
Or, as a one-liner:
> PATH=
"/opt/bin:$(echo $PATH | tr ':' "n" |
grep -v '/opt/bin' | tr -s "n" ':')";
> echo $PATH
/opt/bin:/usr/local/bin:/usr/bin:/bin:/usr/i486-
pc-linux-gnu/gcc-bin/4.1.2:
Quick version of basename
Strip off the longest match to ‘/’:
${file_path##*/}
Relative path within a home directory:
${file_path#$HOME}
Relative path in a sandbox directory:
${file_path##*/$(whoami)/}
Getting some tail
Clean up a directory: ${path%/}
Sandbox root: ${file%$(whoami)/*}
Root of home: ${HOME%$(whoami)*}
Less reliable dirname: ${file_path%/*}
Default values
Common use is with arguments.
> rm -rf $1/*;
What if $1 is empty?
> rm -rf /* # might not be what you want
Dealing with falsity
Common issue: Dealing with a NUL value.
Choose a default.
Assign a default.
Fail.
Use a default value
Lacking an argument, pick a value:
path=${1:-/var/tmp/input};
path=${1:-$input};
path=${1:-/var/cache/$(whoami)};
No effect on $1.
Assign a default value
Empty default assigned a value.
‘$’ interpolation may be nested:
“Default: ‘${default:=/var/tmp/$(whoami)}’”;
“:=” does not work with positional parameters ($1...).
Giving up
Maybe not providing a value is an error.
rm -rf ${path:?Path required.}/*
Code exits with “Path required.” prompt.
For example
#!/bin/bash
# if $1 has a value DEFAULT_PATH is ignored.
# empty $1 checks for non-empty default.
path=${1:-${DEFAULT_PATH:?Empty Default}};
# at this point path is not empty.
The next steps
Special Parameters:
$*, $@, $# Command line
$?, $$, $! Execution
Interpolate command line arguments, process control.
Summary
BASH interpolates variables in one pass.
${...} protect, slice variables
eval multi-pass processing.
<<TAG “here script”
-vx debugging
“Parameter Expansion” in bash(1)

More Related Content

Similar to BASH Variables Part 1: Basic Interpolation

Bash and regular expressions
Bash and regular expressionsBash and regular expressions
Bash and regular expressionsplarsen67
 
BSDM with BASH: Command Interpolation
BSDM with BASH: Command InterpolationBSDM with BASH: Command Interpolation
BSDM with BASH: Command InterpolationWorkhorse Computing
 
Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.VimLin Yo-An
 
Module 03 Programming on Linux
Module 03 Programming on LinuxModule 03 Programming on Linux
Module 03 Programming on LinuxTushar B Kute
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Kang-min Liu
 
Unix 1st sem lab programs a - VTU Karnataka
Unix 1st sem lab programs a - VTU KarnatakaUnix 1st sem lab programs a - VTU Karnataka
Unix 1st sem lab programs a - VTU KarnatakaiCreateWorld
 
Unix shell scripting basics
Unix shell scripting basicsUnix shell scripting basics
Unix shell scripting basicsAbhay Sapru
 
Unix Shell Scripting Basics
Unix Shell Scripting BasicsUnix Shell Scripting Basics
Unix Shell Scripting BasicsDr.Ravi
 
The Unbearable Lightness: Extending the Bash shell
The Unbearable Lightness: Extending the Bash shellThe Unbearable Lightness: Extending the Bash shell
The Unbearable Lightness: Extending the Bash shellRoberto Reale
 
Unix shell scripting basics
Unix shell scripting basicsUnix shell scripting basics
Unix shell scripting basicsManav Prasad
 
Unix Shell Scripting Basics
Unix Shell Scripting BasicsUnix Shell Scripting Basics
Unix Shell Scripting BasicsSudharsan S
 
Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Workhorse Computing
 
Perl Bag of Tricks - Baltimore Perl mongers
Perl Bag of Tricks  -  Baltimore Perl mongersPerl Bag of Tricks  -  Baltimore Perl mongers
Perl Bag of Tricks - Baltimore Perl mongersbrian d foy
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaLin Yo-An
 
Codementor Office Hours with Eric Chiang: Stdin, Stdout: pup, Go, and life at...
Codementor Office Hours with Eric Chiang: Stdin, Stdout: pup, Go, and life at...Codementor Office Hours with Eric Chiang: Stdin, Stdout: pup, Go, and life at...
Codementor Office Hours with Eric Chiang: Stdin, Stdout: pup, Go, and life at...Arc & Codementor
 

Similar to BASH Variables Part 1: Basic Interpolation (20)

Bash and regular expressions
Bash and regular expressionsBash and regular expressions
Bash and regular expressions
 
BSDM with BASH: Command Interpolation
BSDM with BASH: Command InterpolationBSDM with BASH: Command Interpolation
BSDM with BASH: Command Interpolation
 
Unix 5 en
Unix 5 enUnix 5 en
Unix 5 en
 
Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.Vim
 
PHP Tips & Tricks
PHP Tips & TricksPHP Tips & Tricks
PHP Tips & Tricks
 
Module 03 Programming on Linux
Module 03 Programming on LinuxModule 03 Programming on Linux
Module 03 Programming on Linux
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
Unix 1st sem lab programs a - VTU Karnataka
Unix 1st sem lab programs a - VTU KarnatakaUnix 1st sem lab programs a - VTU Karnataka
Unix 1st sem lab programs a - VTU Karnataka
 
Unix shell scripting basics
Unix shell scripting basicsUnix shell scripting basics
Unix shell scripting basics
 
Unix Shell Scripting Basics
Unix Shell Scripting BasicsUnix Shell Scripting Basics
Unix Shell Scripting Basics
 
The Unbearable Lightness: Extending the Bash shell
The Unbearable Lightness: Extending the Bash shellThe Unbearable Lightness: Extending the Bash shell
The Unbearable Lightness: Extending the Bash shell
 
Cpsh sh
Cpsh shCpsh sh
Cpsh sh
 
Unix shell scripting basics
Unix shell scripting basicsUnix shell scripting basics
Unix shell scripting basics
 
Shell scripting
Shell scriptingShell scripting
Shell scripting
 
Unix Shell Scripting Basics
Unix Shell Scripting BasicsUnix Shell Scripting Basics
Unix Shell Scripting Basics
 
Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!
 
Perl Bag of Tricks - Baltimore Perl mongers
Perl Bag of Tricks  -  Baltimore Perl mongersPerl Bag of Tricks  -  Baltimore Perl mongers
Perl Bag of Tricks - Baltimore Perl mongers
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim Perlchina
 
Codementor Office Hours with Eric Chiang: Stdin, Stdout: pup, Go, and life at...
Codementor Office Hours with Eric Chiang: Stdin, Stdout: pup, Go, and life at...Codementor Office Hours with Eric Chiang: Stdin, Stdout: pup, Go, and life at...
Codementor Office Hours with Eric Chiang: Stdin, Stdout: pup, Go, and life at...
 
Cleancode
CleancodeCleancode
Cleancode
 

More from Workhorse Computing

Wheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility ModulesWheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility ModulesWorkhorse Computing
 
Paranormal statistics: Counting What Doesn't Add Up
Paranormal statistics: Counting What Doesn't Add UpParanormal statistics: Counting What Doesn't Add Up
Paranormal statistics: Counting What Doesn't Add UpWorkhorse Computing
 
The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.Workhorse Computing
 
Generating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in PosgresqlGenerating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in PosgresqlWorkhorse Computing
 
The W-curve and its application.
The W-curve and its application.The W-curve and its application.
The W-curve and its application.Workhorse Computing
 
Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.Workhorse Computing
 
Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.Workhorse Computing
 
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6Workhorse Computing
 
Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.Workhorse Computing
 

More from Workhorse Computing (20)

Wheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility ModulesWheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility Modules
 
mro-every.pdf
mro-every.pdfmro-every.pdf
mro-every.pdf
 
Paranormal statistics: Counting What Doesn't Add Up
Paranormal statistics: Counting What Doesn't Add UpParanormal statistics: Counting What Doesn't Add Up
Paranormal statistics: Counting What Doesn't Add Up
 
The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.
 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
 
Generating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in PosgresqlGenerating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in Posgresql
 
Findbin libs
Findbin libsFindbin libs
Findbin libs
 
Memory Manglement in Raku
Memory Manglement in RakuMemory Manglement in Raku
Memory Manglement in Raku
 
Effective Benchmarks
Effective BenchmarksEffective Benchmarks
Effective Benchmarks
 
Metadata-driven Testing
Metadata-driven TestingMetadata-driven Testing
Metadata-driven Testing
 
The W-curve and its application.
The W-curve and its application.The W-curve and its application.
The W-curve and its application.
 
Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.
 
Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.
 
Smoking docker
Smoking dockerSmoking docker
Smoking docker
 
Getting Testy With Perl6
Getting Testy With Perl6Getting Testy With Perl6
Getting Testy With Perl6
 
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
 
Neatly folding-a-tree
Neatly folding-a-treeNeatly folding-a-tree
Neatly folding-a-tree
 
Light my-fuse
Light my-fuseLight my-fuse
Light my-fuse
 
Paranormal stats
Paranormal statsParanormal stats
Paranormal stats
 
Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.
 

Recently uploaded

How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 

Recently uploaded (20)

How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 

BASH Variables Part 1: Basic Interpolation

  • 1. Don’t BASH your head in: Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com
  • 2. Quick review BASH is interpreted. Loops are re-parsed. Variables can appear anywhere. Unlike Perl, Python, Ruby, Go, Haskell, Scala, Scheme, Which separate statements from var’s.
  • 3. Basic Variables Assignments to foo: foo=’$files’; literal ‘$files’.
  • 4. Basic Variables Assignments to foo: foo=’$files’; literal ‘$files’. foo=”$files”; interpolated value of files.
  • 5. Basic Variables Assignments to foo: foo=’$files’; literal ‘$files’. foo=”$files”; interpolated value of files. foo=$(ls $files); command output.
  • 6. Basic Variables Assignments to foo: foo=’$files’; literal ‘$files’. foo=”$files”; interpolated value of files. foo=$(ls $files); command output. foo=”$(ls $files)”; string with listing of files.
  • 7. Basic Variables Assignments to foo: foo=’$files’; literal ‘$files’. foo=”$files”; interpolated value of files. foo=$(ls $files); command output. Most of the work is interpolating: echo “Your files are: $(ls $somedir)”;
  • 8. De-mangling variable names > foo=’bar’; > echo “foo$foo”; ”foobar” > echo “$bar_foo”; “” Oops: Variable “bar_foo” doesn’t exist.
  • 9. De-mangling variable names > foo=’bar’; > echo “foo$foo”; ”foobar” > echo “$bar_foo”; “” Isolate ‘foo’ as variable name: “${foo}_bar # “bar_bar”
  • 12. Variable commands # interpolate each command into the loop for i in $cmd1 $cmd2 $cmd3 do $i $args; done
  • 15. Really, anywhere! foo=’bar’; $foo=’blort’; Q: What happens? A: Nada. bash: bar=blort: command not found
  • 16. Your one chance at success BASH parses in two phases: Lexical substitution & tokenizing. Execution. Variables have to expand on the first pass to be used. “foo=blort” cannot be executed, so it failed.
  • 17. A second chance in life ‘eval’ adds one cycle. Interpolates variables. Passes result to the shell. ‘++’ is two levels deep. > eval"$foo=blort"; + eval bar=blort ++ bar=blort > echo $bar; + echo blort blort
  • 18. Or a third chance... eval “eval … “; Work out what is happening: a=’$HOME/?.*’; b=’foo’; c=eval “eval $a $b”’;
  • 19. Verbosity & Execution See what bash is doing with the variables: > set -vx;
  • 20. Verbosity & Execution See what bash is doing with the variables: > set -vx; echo -ne "033]0;./$(basename $PWD) 007" +++ basename /sandbox/lembark/writings/RockfordLUG/bash ++ echo -ne '033]0;./bash 007' >
  • 21. Verbosity & Execution See what bash is doing with the variables: > set -vx; echo -ne "033]0;./$(basename $PWD) 007" +++ basename /sandbox/lembark/writings/RockfordLUG/bash ++ echo -ne '033]0;./bash 007' >
  • 22. “unset” removes variables > unset PROMPT_COMMAND; > set -vx; >
  • 23. Or set verbosity in the script #!/bin/bash -vx … or localize the verbosity: set -vx; do something set -;
  • 24. Verbosity & Execution > unset PROMPT_COMMAND; > set -vx; > foo=bar; what I typed foo=bar; what BASH read + foo=bar single ‘+’is one level deep
  • 25. Verbosity & Execution > unset PROMPT_COMMAND; > set -vx; > foo=bar; what I typed foo=bar; what BASH read + foo=bar single ‘+’is one level deep > $foo='blort'; >foo='blort'; + bar=blort no second chance to re-parse
  • 26. Verbosity & Execution > unset PROMPT_COMMAND; > set -vx; > foo=bar; what I typed foo=bar; what BASH read + foo=bar single ‘+’is one level deep > $foo='blort'; >foo='blort'; + bar=blort no second chance to re-parse bash: bar=blort: command not found
  • 27. Why use ‘-vx’? -v alone is useful sometimes. -x alone usually isn’t.
  • 28. Example: Hidden disk hogs #!/bin/bash dirs="/home/$(whoami)/.*"; cmd="du -msx $dirs | sort -rn | head -3"; eval "$cmd";
  • 29. Buggy hogs $ ./y 1232 /home/lembark/. 0 /home/lembark/..
  • 30. Add verbosity #!/bin/bash set -vx; dirs="/home/$(whoami)/.*"; cmd="du -msx $dirs | sort -rn | head -3"; eval "$cmd";
  • 31. Shows the bug: . & .. $ ./y dirs="/home/$(whoami)/.*"; ++ whoami + dirs='/home/lembark/.*' cmd="du -msx $dirs | sort -rn | head -3"; + cmd='du -msx /home/lembark/.* | sort -rn | head -3' eval "$cmd"; + eval 'du -msx /home/lembark/.* | sort -rn | head -3' du -msx /home/lembark/.* | sort -rn | head -3 ++ sort -rn ++ head -3 ++ du -msx /home/lembark/. /home/lembark/.. /home/lembark/.aceinnovative /home/lembark/.adobe <snip> 1232 /home/lembark/. 0 /home/lembark/..
  • 32. Fix: Add a letter #!/bin/bash set -vx; dirs="/home/$(whoami)/.[a-z]*"; cmd="du -msx $dirs | sort -rn | head -3"; eval "$cmd";
  • 33. Start with the right dirs $ ./y dirs="/home/$(whoami)/.[a-z]*"; ++ whoami + dirs='/home/lembark/.[a-z]*' cmd="du -msx $dirs | sort -rn | head -3"; + cmd='du -msx /home/lembark/.[a-z]* | sort -rn | head -3' eval "$cmd"; + eval 'du -msx /home/lembark/.[a-z]* | sort -rn | head -3' du -msx /home/lembark/.[a-z]* | sort -rn | head -3 ++ sort -rn ++ head -3 ++ du -msx /home/lembark/.aceinnovative /home/lembark/.adobe <snip> 270 /home/lembark/.openoffice 244 /home/lembark/.mozilla 193 /home/lembark/.config
  • 34. Compare: Only “-v” $ ./y dirs="/home/$(whoami)/.[a-z]*"; cmd="du -msx $dirs | sort -rn | head -3"; eval "$cmd"; du -msx /home/lembark/.[a-z]* | sort -rn | head -3 270 /home/lembark/.openoffice 244 /home/lembark/.mozilla 193 /home/lembark/.config
  • 35. Compare: Only “-x” $ ./y ++ whoami + dirs='/home/lembark/.[a-z]*' + cmd='du -msx /home/lembark/.[a-z]* | sort -rn | head -3' + eval 'du -msx /home/lembark/.[a-z]* | sort -rn | head -3' ++ sort -rn ++ head -3 ++ du -msx /home/lembark/.aceinnovative /home/lembark/.adobe <snip> 270 /home/lembark/.openoffice 244 /home/lembark/.mozilla 193 /home/lembark/.config
  • 36. Command execution We all remember backticks: a=`ls -al ~`’;
  • 37. Command execution We all remember backticks: a=`ls -al ~`’; Better off forgotten: No way to nest them for one. Hard to read for another.
  • 38. Command execution BASH offers a better way: $( ... ) i.e., “interpolate subshell output”. Output of arbitrary commands: files=$(ls ~); jobs=$( grep ‘MHz’ /proc/cpuinfo | wc -l ); echo -e “DiskHogz:n$(du -msx *|sort -rn|head)”;
  • 39. Twisting a path with basename basename locates input for next step. cmd=’/image/bin/extract-hi-res’; dir=’../raw’; cd high-res || exit -1; for i in ../low-res/culled/*; do echo “Input: ‘$i’”; $cmd $dir/$(basename $i .ppm).nef; done
  • 40. Twisting a path with basename Quotes hilite whitespace in $1. Don’t leave home without them... cmd=’/image/bin/extract-hi-res’; dir=’../raw’; cd high-res || exit -1; for i in ../low-res/culled/*; do echo “Input: ‘$i’”; $cmd $dir/$(basename $i .ppm).nef; done
  • 41. Being there A “here script” is “appended from stdin”. Double-quotish. > perl -MCPAN -E shell <<CPAN 2>&1 | tee a; upgrade install Module::FromPerlVer q CPAN
  • 42. Being there A “here script” is “appended from stdin”. Double-quotish, into stdin. > perl -MCPAN -E shell <<CPAN 2>&1 | tee a; upgrade install Module::FromPerlVer q CPAN
  • 43. Being there Closing tag sends EOF (^D) to command: > perl -MCPAN -E shell <<CPAN 2>&1 | tee a; upgrade install Module::FromPerlVer CPAN
  • 44. Being there module=’Module::FromPerlVer’; > perl -MCPAN -E shell <<CPAN 2>&1 | tee a; upgrade install $module CPAN
  • 45. Being there #!/bin/bash ... path=”$mysql_d/$tspace”; mkdir -p $path || exit -2; mysql -U$user -P$pass <<SQL || exit -3; create tablespace $tspace using ‘$path’ … ; create table big ( … ) tablespace $tspace; SQL
  • 46. Being there mysql -U$user -P$pass <<SQL || exit -3; create tablespace $tspace using ‘$path’ … ; create table $(cat $table-1.sql) tablespace $tspace; SQL
  • 47. Slicing with curlies Remove strings from the head or tail of a string. ${i#glob} ${i%glob} ${i##glob} ${i%%glob}
  • 48. Slicing with curlies Slice the head: ${i#glob} ${i##glob} # is shortest match ## is longest match
  • 49. Slicing with curlies Slice the tail: ${i%glob} ${i%%glob} % is shortest match %% is longest match
  • 50. Stripping a prefix. Say you want to prefix ‘/opt/bin’ onto a PATH. But it may already be there. You don’t know if someone else hacked the path. Q: How can we put ‘/opt/bin’ at the front, once?
  • 51. Stripping a prefix. Say you want to prefix ‘/opt/bin’ onto a PATH. But it may already be there. You don’t know if someone else hacked the path. Q: How can we put ‘/opt/bin’ at the front, once? A: Take it off each time.
  • 52. Striptease. ‘#’ strips off leading content. Say we tried this: PATH=”/opt/bin:${PATH#/opt/bin:}”; OK, I can run it a hundred times.
  • 53. Path hack striptease. ‘#’ strips off leading content. Say we tried this: PATH=”/opt/bin:${PATH#/opt/bin:}”; OK, I can run it a hundred times. Until /opt/bin isn’t first: “~/bin:/opt/bin: ...”
  • 54. Globs save the day Find everything up to the first match: PATH=”/opt/bin:${PATH#*/opt/bin:}”; > echo $PATH; /usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/ i486-pc-linux-gnu/gcc-bin/4.1.2
  • 55. Globs save the day Find everything up to the first match: PATH=”/opt/bin:${PATH#*/opt/bin:}”; > echo ${PATH#*/opt/bin:}; + echo /usr/local/bin:/usr/bin:/bin:/opt/bin:/ usr/i486-pc-linux-gnu/gcc-bin/4.1.2
  • 56. Globs save the day Find everything up to the first match: PATH=”/opt/bin:${PATH#*/opt/bin:}”; > echo ${PATH#*/opt/bin:}; + echo /usr/local/bin:/usr/bin:/bin:/opt/bin:/ usr/i486-pc-linux-gnu/gcc-bin/4.1.2
  • 57. Globs save the day Find everything up to the first match: PATH=”/opt/bin:${PATH#*/opt/bin:}”; /usr/i486-pc-linux-gnu/gcc-bin/4.1.2
  • 58. Fixing the path Takes a bit more logic: Strip /opt/bin out of the path. Paste it onto the front. Globs aren’t smart enough.
  • 59. Fixing the path Takes a bit more logic: First break up the path. > echo $PATH | tr ':' "n" /opt/bin /usr/local/bin /usr/bin /opt/bin /bin /usr/i486-pc-linux-gnu/gcc-bin/4.1.2
  • 60. Fixing the path Takes a bit more logic: Then remove ‘/opt/bin’. > echo $PATH | tr ':' "n" | grep -v '/opt/bin' /usr/local/bin /usr/bin /bin /usr/i486-pc-linux-gnu/gcc-bin/4.1.2
  • 61. Fixing the path Takes a bit more logic: Recombine them. > a=$(echo $PATH | tr ':' "n" | grep -v '/opt/bin' | tr "n" ':'); > echo $a /usr/local/bin:/usr/bin:/bin:/usr/i486-pc-linux- gnu/gcc-bin/4.1.2::
  • 62. Fixing the path Takes a bit more logic: Prefix ‘/opt/bin’. > a=$(echo $PATH | tr ':' "n" | grep -v '/opt/bin' | tr "n" ':'); > echo “/opt/bin:$a”; /opt/bin:/usr/local/bin:/usr/bin:/bin:/usr/i486- pc-linux-gnu/gcc-bin/4.1.2::
  • 63. Fixing the path Takes a bit more logic: Or, as a one-liner: > PATH= "/opt/bin:$(echo $PATH | tr ':' "n" | grep -v '/opt/bin' | tr -s "n" ':')"; > echo $PATH /opt/bin:/usr/local/bin:/usr/bin:/bin:/usr/i486- pc-linux-gnu/gcc-bin/4.1.2:
  • 64. Quick version of basename Strip off the longest match to ‘/’: ${file_path##*/} Relative path within a home directory: ${file_path#$HOME} Relative path in a sandbox directory: ${file_path##*/$(whoami)/}
  • 65. Getting some tail Clean up a directory: ${path%/} Sandbox root: ${file%$(whoami)/*} Root of home: ${HOME%$(whoami)*} Less reliable dirname: ${file_path%/*}
  • 66. Default values Common use is with arguments. > rm -rf $1/*; What if $1 is empty? > rm -rf /* # might not be what you want
  • 67. Dealing with falsity Common issue: Dealing with a NUL value. Choose a default. Assign a default. Fail.
  • 68. Use a default value Lacking an argument, pick a value: path=${1:-/var/tmp/input}; path=${1:-$input}; path=${1:-/var/cache/$(whoami)}; No effect on $1.
  • 69. Assign a default value Empty default assigned a value. ‘$’ interpolation may be nested: “Default: ‘${default:=/var/tmp/$(whoami)}’”; “:=” does not work with positional parameters ($1...).
  • 70. Giving up Maybe not providing a value is an error. rm -rf ${path:?Path required.}/* Code exits with “Path required.” prompt.
  • 71. For example #!/bin/bash # if $1 has a value DEFAULT_PATH is ignored. # empty $1 checks for non-empty default. path=${1:-${DEFAULT_PATH:?Empty Default}}; # at this point path is not empty.
  • 72. The next steps Special Parameters: $*, $@, $# Command line $?, $$, $! Execution Interpolate command line arguments, process control.
  • 73. Summary BASH interpolates variables in one pass. ${...} protect, slice variables eval multi-pass processing. <<TAG “here script” -vx debugging “Parameter Expansion” in bash(1)