Why the following does not print anything?

```bash
args=()
echo test | while read option
do
args+=("$option" "$option")
break
done

echo "|${args[@]}|"
```
Jun 27, 6:09pm

The issue in your script is due to variable scope in Bash. In Bash, variables declared inside a while loop (or any subshell) are local to that subshell and do not persist outside of it. The while loop in your script is part of a pipeline (echo test | while ...), which runs in a subshell. As a result, the args array is modified inside the subshell, but the parent shell (where you try to print args) does not see those changes.


Why it happens

  • The while loop runs in a subshell because it is part of a pipeline (echo test | while ...).
  • The args array is modified inside the subshell, but the parent shell retains its original value (empty).

How to fix it

To ensure the args array is modified in the parent shell, avoid using a pipeline. Instead, use here-strings or process substitution to feed input to the while loop without creating a subshell.

Option 1: Use a here-string

bash
args=()
while read option
do
    args+=("$option" "$option")
    break
done <<< "test"

echo "|${args[@]}|"

Output:

text
|test test|

Option 2: Use process substitution (if you need to read from a command)

bash
args=()
while read option
do
    args+=("$option" "$option")
    break
done < <(echo test)

echo "|${args[@]}|"

Output:

text
|test test|

Option 3: Avoid the pipeline entirely

bash
args=()
option="test"
args+=("$option" "$option")
echo "|${args[@]}|"

Output:

text
|test test|

Key Takeaway

  • Pipelines create subshells in Bash, and variables modified in a subshell do not affect the parent shell.
  • Use here-strings (<<<), process substitution (< <(...)), or direct assignment to avoid subshell issues.
Jun 27, 6:09pm

This is a shared conversation and may include unverified content that doesn't reflect Mistral AI's views. Login to resume chatting.

Vibe can make mistakes. Check answers. Learn more