> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bash Single Character Pattern

A single character pattern in Bash is a globbing metacharacter used in pathname expansion and string matching that evaluates to exactly one arbitrary character. The primary operator for this is the question mark (`?`), while bracket expressions (`[...]`) provide constrained single-character matching.

## The `?` Metacharacter

The `?` operator matches any single character in a string or filename. It requires exactly one character to be present; it evaluates strictly to a length of one and will not match zero characters or multiple characters.

```bash theme={"dark"}

# Evaluates true for: a1c, aBc, a_c

# Evaluates false for: ac, abbc
[[ $string == a?c ]]


# Expands to files with exactly one character between 'doc' and '.txt'
ls doc?.txt
```

**Evaluation Rules:**

* **Path Boundaries:** When used in pathname expansion, `?` will not match a directory separator slash (`/`).
* **Hidden Files:** By default, `?` will not match a leading period (`.`) representing a hidden file or directory. The shell option `shopt -s dotglob` must be enabled to override this behavior.
* **Null Byte:** It cannot match the null character (`\0`), as Bash strings are null-terminated.

## Bracket Expressions `[...]`

A bracket expression evaluates to exactly one character that exists within the enclosed set or range. Despite containing multiple characters inside the brackets, the entire construct represents only a single character position in the resulting match.

```bash theme={"dark"}

# Evaluates true if the string is exactly 'a', 'b', or 'c'
[[ $string == [abc] ]]


# Expands to files starting with a single digit in the ASCII range '0' through '9'
ls [0-9]*
```

**Evaluation Rules & Pitfalls:**

* **Collation and Locale (`LC_COLLATE`):** In many default locales (e.g., `en_US.UTF-8`), bracket ranges like `[A-Z]` or `[a-z]` use dictionary sorting (`aAbBcCdD...`). Consequently, `[A-Z]` will unexpectedly match lowercase letters (except 'a'), and `[a-z]` will match uppercase letters (except 'Z'). To enforce strict ASCII byte-value sorting, developers must set `LC_COLLATE=C` or use POSIX character classes (e.g., `[[:upper:]]`).
* **POSIX Character Classes:** Supports classes like `[[:alpha:]]` or `[[:digit:]]`, which resolve to a single character match from within that class while remaining locale-aware and safe from range collation issues.
* **Negation:** Prefixing the set with `!` or `^` immediately after the opening bracket inverts the match, evaluating to exactly one character *not* present in the defined set.

```bash theme={"dark"}
# Evaluates true for any single character that is NOT 'a', 'b', or 'c'
[[ $string == [!abc] ]]
[[ $string == [^abc] ]]
```

**Matching Literals Inside Brackets:**
Bash natively supports backslash escaping inside bracket expressions. Characters that normally possess special meaning within brackets (`]`, `-`, `^`, `!`) can be safely escaped with a backslash (`\`) to be treated as literal characters.

```bash theme={"dark"}
[[ $string == [a\]c] ]]  # Matches 'a', ']', or 'c'
[[ $string == [a\-c] ]]  # Matches 'a', '-', or 'c'
[[ $string == [\!abc] ]] # Matches '!', 'a', 'b', or 'c'
```

Alternatively, Bash also respects POSIX positional rules to match these characters as literals without escaping:

* **Literal `]`**: Placed as the first character in the set, or immediately following the negation operator (`[]abc]` or `[!]]`).
* **Literal `-`**: Placed as the first or last character in the set (`[-abc]` or `[abc-]`).
* **Literal `^` or `!`**: Placed anywhere except the first position (`[ab!c^]`).

## Contextual Execution

Single character patterns are evaluated dynamically based on the syntax context:

1. **Pathname Expansion (Globbing):** Evaluated against the file system. If no file matches the pattern, Bash leaves the pattern as a literal string by default (modifiable via `shopt -s nullglob` or `failglob`).
2. **Conditional Expressions (`[[ ... ]]`):** Evaluated as a pattern matching operator against strings on the right side of the `==` or `!=` operators.
3. **Case Statements:** Evaluated against the test string to determine execution branching.

## Escaping and Literals

To suppress the special meaning of single character patterns and treat them as literal characters outside of bracket expressions, they must be quoted or escaped using a backslash (`\`), single quotes (`'...'`), or double quotes (`"..."`).

```bash theme={"dark"}

# Evaluates true only for the exact 5-character literal string "file?"
[[ $string == file\? ]]
[[ $string == "file?" ]]
[[ $string == 'file?' ]]
```

## Extended Globbing (`extglob`)

When the `extglob` shell option is enabled (`shopt -s extglob`), Bash alters the behavior of `?` when combined with parentheses. This creates a composite pattern that matches zero or one occurrence of a specified pattern list, deviating from the strict "exactly one character" rule of the standalone `?`.

```bash theme={"dark"}
shopt -s extglob


# Evaluates true for "", "pattern1", or "pattern2"
[[ $string == ?(pattern1|pattern2) ]]
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Bash Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
