rc-shell: document if-not pitfall, stderr redirect, fn body syntax
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2dd6fea2e6
commit
742716dcec
|
|
@ -34,9 +34,6 @@ result=`split{command} # split using 'split' instead of $ifs
|
||||||
if(test -f file) {
|
if(test -f file) {
|
||||||
echo exists
|
echo exists
|
||||||
}
|
}
|
||||||
if not { # separate statement, new line
|
|
||||||
echo missing
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i in 1 2 3) { echo $i }
|
for(i in 1 2 3) { echo $i }
|
||||||
for(i) { echo $i } # iterates over $* if no list
|
for(i) { echo $i } # iterates over $* if no list
|
||||||
|
|
@ -51,24 +48,53 @@ case *
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**`if not` is unreliable** — though documented in the rc manual, `if not` causes syntax errors in practice. Use a flag variable instead:
|
||||||
|
|
||||||
|
```
|
||||||
|
ok=0
|
||||||
|
if(test -f file) { echo exists; ok=1 }
|
||||||
|
if(~ $ok 0) echo missing
|
||||||
|
```
|
||||||
|
|
||||||
|
Chained `if` statements serve as logical AND:
|
||||||
|
|
||||||
|
```
|
||||||
|
if(test -f file) if(~ $mode rw) echo writable
|
||||||
|
```
|
||||||
|
|
||||||
## Functions & Pattern Matching
|
## Functions & Pattern Matching
|
||||||
|
|
||||||
```
|
```
|
||||||
fn name { echo $* $1 } # define (all args, first arg)
|
fn name { # always use multi-line bodies
|
||||||
|
echo $* $1 # $* all args, $1 first arg
|
||||||
|
}
|
||||||
fn name # remove definition
|
fn name # remove definition
|
||||||
~ $file *.txt # pattern match (sets $status)
|
~ $file *.txt # pattern match (sets $status)
|
||||||
if(~ $#list 0) { echo empty }
|
if(~ $#list 0) { echo empty }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Single-line function bodies with `;` cause syntax errors.** Always use multi-line:
|
||||||
|
|
||||||
|
```
|
||||||
|
# WRONG: fn die { echo $* >[1=2]; exit 1 }
|
||||||
|
fn die {
|
||||||
|
echo $* >[1=2]
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Redirection & Pipes
|
## Redirection & Pipes
|
||||||
|
|
||||||
```
|
```
|
||||||
>out >>out <in <<EOF # stdout, append, stdin, here doc
|
>out >>out <in <<EOF # stdout, append, stdin, here doc
|
||||||
>[2]err >[2=1] >[2=] # fd 2 to file, fd 2 to fd 1, close fd 2
|
>[2]err >[2=] # fd 2 to file, close fd 2
|
||||||
|
>[1=2] # stdout to stderr (write to stderr)
|
||||||
|
>[2=1] # stderr to stdout
|
||||||
<[0=3] # fd 0 from fd 3
|
<[0=3] # fd 0 from fd 3
|
||||||
<{cmd} >{cmd} <>{cmd} # process substitution
|
<{cmd} >{cmd} <>{cmd} # process substitution
|
||||||
cmd1 | cmd2 # pipe
|
cmd1 | cmd2 # pipe
|
||||||
|[2] |[1=2] # pipe fd 2, pipe fd 2 to fd 1
|
|[2] |[1=2] # pipe fd 2, pipe fd 2 to fd 1
|
||||||
|
{ cmd1; cmd2 } > file # redirect block stdout to file
|
||||||
```
|
```
|
||||||
|
|
||||||
## Operators
|
## Operators
|
||||||
|
|
@ -88,10 +114,11 @@ cmd1 | cmd2 # pipe
|
||||||
|
|
||||||
- Backticks `{cmd}`, not `$(cmd)`
|
- Backticks `{cmd}`, not `$(cmd)`
|
||||||
- Lists `(a b c)`, 1-indexed
|
- Lists `(a b c)`, 1-indexed
|
||||||
- `if not` on new line
|
- No reliable `if/else`: use flag variable + chained `if` instead of `if not`
|
||||||
- `test` or `~`, not `[[ ]]`
|
- `test` or `~`, not `[[ ]]`
|
||||||
- `$#var` not `${#var}`, `$"var` not `"$*"`
|
- `$#var` not `${#var}`, `$"var` not `"$*"`
|
||||||
- `>[2=1]` not `2>&1`
|
- `>[1=2]` to write to stderr (stdout→stderr), `>[2=1]` for stderr→stdout
|
||||||
|
- `>[2]file` redirects fd 2 to a file; bare `>[2]` (no filename) is a syntax error
|
||||||
- No `${var:-default}`
|
- No `${var:-default}`
|
||||||
- `fn name` not `function name`
|
- `fn name` not `function name`
|
||||||
- Single quotes only (double quotes not special)
|
- Single quotes only (double quotes not special)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue