Variables and Expansion
Everything that happens between the text you type and the argument list the command finally receives: quoting, parameter expansion, arrays, word splitting, and globbing. Most of the bash bugs interviewers ask about — a filename with spaces, an empty variable that eats an argument — are expansion bugs, which makes this the densest part of the language.
part ofBashoverview, primer and where to startread it →on this pageshowhide
explore
- Variables, declare and Special Parameters5 questions
- Parameter Expansion Operators5 questions
- Indexed Arrays5 questions
- Associative Arrays and Namerefs5 questions
- Quoting Rules5 questions
- Word Splitting and IFS5 questions
- Globbing and Pattern Matching5 questions
- Expansion Order and Brace Expansion4 questions
questions
page 2 of 2A colleague adds `IFS=$'\n\t'` near the top of a shared bash script, saying it makes the script safer. What does that global change actually buy, what does it fail to protect against, and what can it break?
basics
~20 sIt removes the space from the separator set, so unquoted expansions no longer split on spaces — only on newlines and tabs. It does not stop globbing, does not make quoting unnecessary, and silently changes any code that relied on space splitting, including sourced libraries.
In bash with `v=''`, the function `count() { echo $#; }` prints different numbers for `count $v` and `count "$v"`. What does each print, and why?
basics
~20 scount $v prints 0 and count "$v" prints 1. An unquoted empty expansion is split on IFS into zero words, so no argument is passed at all, while double quotes force it to become exactly one argument, an empty string.
In bash, after `arr=(a b c); unset 'arr[1]'`, what do `${#arr[@]}` and `${!arr[@]}` report, and why is a C-style loop from 0 to `${#arr[@]}-1` the wrong way to iterate an array?
basics
~20 sBash arrays are sparse: unset removes index 1 without renumbering, so ${#arr[@]} is 2 while the live indices from ${!arr[@]} are 0 and 2. A counter loop bounded by the count would read index 1, which no longer exists, and never reach index 2.
A bash associative array `declare -A opts` may legitimately hold empty-string values. How do you test whether a given key is present, as opposed to present-but-empty?
basics
~20 sUse [[ -v opts[key] ]], which is true when the key exists whatever its value (bash 4.3+ accepts array subscripts here). The pre-4.3 equivalent is [[ -n ${opts[key]+x} ]]. Testing [[ -n ${opts[key]} ]] conflates absent with empty.
In bash, `$RANDOM` and `$SECONDS` return a different value each time they are read. What do these shell-maintained variables give you, and what should `$RANDOM` not be used for?
basics
~20 sEach reference to $RANDOM yields a new pseudo-random integer between 0 and 32767, and $SECONDS counts whole seconds since the shell started. $RANDOM is a seeded pseudo-random generator, so it must not be used for anything security-sensitive.
What does the pattern `**` expand to in bash, what has to be enabled for it to be recursive, and how does `for f in **/*.js` differ from `find . -name '*.js'`?
basics
~20 sWithout shopt -s globstar, ** behaves like a single * and stays inside one directory level. With globstar on (bash 4.0+), **/ matches zero or more directories, so **/*.js recurses. Unlike find, it still skips hidden entries and expands entirely in memory.
In a bash script you need one string containing a literal single quote and another containing a real tab character. Single quotes have no escape character — how do you build each of these, and why is `echo -e` not the answer?
basics
~20 sClose, escape, reopen: 'it'\''s' produces it's because single quotes cannot contain an escaped quote. For control characters use ANSI-C quoting, $'\t', which bash converts to a real tab before the command ever runs; printf is the portable alternative to echo -e.
Since bash expands a command line only once, when does a script genuinely need `eval` to force a second pass, and which bash features let you avoid reaching for it?
basics
~20 seval re-parses its argument as a fresh command line, giving a second full round of expansion. It is genuinely needed only when the command's structure, not just its arguments, is computed at run time — for example running the shell assignments a tool prints. Arrays, printf -v and namerefs cover most other cases.
A bash deploy script holds an environment name in $ENV (PROD or STAGING) and reads configuration from variables named PROD_HOST and STAGING_HOST. How does bash's indirect expansion ${!name} let you read the right one, and how does it compare with using eval?
basics
~20 sBuild the variable name in a string, then expand it indirectly: key="${ENV}_HOST"; host="${!key}". Bash reads the variable whose name is the value of key. Unlike eval, it substitutes only a value and never executes the name as code.
showing 31–39 of 39