Skip to main content
The # (hash or pound) character in Bash is an overloaded lexical token that serves multiple distinct syntactic functions depending on its execution context. It operates as a comment initiator, a parameter expansion modifier (for prefix truncation, length calculation, and pattern substitution anchoring), a special parameter for argument counting, a radix indicator in arithmetic evaluation, and an event designator in history expansion.

1. Lexical Comments

When # appears as the first character of a word (unquoted and unescaped), the Bash parser treats it and all subsequent characters on that line as a comment. The parser discards the comment during the tokenization phase before command execution.

2. Parameter Expansion: Prefix Truncation

Within parameter expansion, # and ## strip a matching prefix pattern from the value of a parameter. The pattern undergoes tilde expansion, parameter expansion, command substitution, and arithmetic expansion.
  • Shortest Match (#): Deletes the shortest matching prefix.
  • Longest Match (##): Deletes the longest matching prefix.
If the pattern matches the beginning of the expanded value, the result is the expanded value with the matching prefix deleted. If the parameter is an array subscripted by @ or *, or if it is the positional parameters (@ or *), the prefix truncation operation is applied to each element individually, expanding to a list of the modified elements.

3. Parameter Expansion: Pattern Substitution Anchor

In pattern substitution, a # immediately following the first slash acts as a prefix anchor. It forces the pattern match to occur only at the beginning of the expanded value of the parameter.
Similar to prefix truncation, if this expansion is applied to an array subscripted by @ or *, or to the positional parameters, the anchored substitution is applied to each element individually.

4. Parameter Expansion: Length Evaluation

When # is placed immediately before a parameter name within parameter expansion braces, it evaluates the length of the parameter’s contents rather than returning the contents themselves.
  • String Length: Evaluates to the number of characters in the parameter. If the parameter is an array referenced without a subscript, it defaults to index 0 and evaluates the string length of the first element (${parameter[0]}).
  • Array Element Count: If the parameter is an array subscripted by @ or *, it evaluates to the total number of populated elements in the array.
  • Positional Parameter Count: If the parameter is @ or *, it evaluates to the number of positional parameters currently set.

5. Special Parameter: Argument Count

In strict Bash terminology, # is a special parameter maintained by the shell, not a variable (variables are a specific subset of parameters requiring valid alphanumeric names). The parameter expansion $# evaluates to a decimal integer representing the total number of positional parameters passed to the current script or the current function scope.

6. Arithmetic Evaluation: Base (Radix) Indicator

Within arithmetic expansion contexts (such as $(( )), (( )), or the let builtin), # acts as a delimiter separating an arithmetic base from its corresponding integer value.
The base must be a decimal integer between 2 and 64. The number is evaluated according to the specified base. If the base is omitted, base 10 is assumed (unless prefixed by 0 for octal or 0x for hexadecimal).

7. Interactive History Expansion

In interactive shells with history expansion enabled, # functions as an event designator when prefixed with !. The !# sequence evaluates to the entire command line typed so far before the current cursor position.
Tired of Poor Bash Skills? Fix That With Deep Grasping!Learn More