add parameter expansion, arithmetic, set -e/-x/pipefail, trap, eval, exec

- ${#v}, ${v#p} ${v##p} ${v%p} ${v%%p}, ${v/p/r} ${v//p/r} ${v/#p/r}
  ${v/%p/r}, ${v:off:len}, ${v-w} ${v:=w} ${v:+w} ${v:?msg}; nested ${}
- arithmetic expansion $((...)) with the C operators, ** and assignments
- set -e, set -x, set -o pipefail (also as gosh options, passed on to
  subshells); set shows variables, set -o the options
- trap for EXIT and signals; scripts with an EXIT trap run it on
  SIGINT/SIGTERM/SIGHUP too
- eval, exec (also exec > file without a command), $!, wait pid

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Florian WaltherandClaude Opus 5.5 committed 2026-10-04 21:15:24 +02:00
1 parent f66cf538c0
commit 1f507f6562
20 files changed
+2408 -93

No files matched your search

+174 -5
View File
@@ -68,6 +68,14 @@ become
.B \-i
Force interactive mode, even if standard input is not a terminal.
.TP
.BR \-e ", " \-x ", " "\-o \fIoption\fP"
Set options like
.BR set ,
e.g.
.B gosh \-e script
or
.BR "gosh \-o pipefail \-c" " ...".
.TP
.BR \-l ", " \-\-login
Act as a login shell and read the profile files (see
.BR "STARTUP FILES" ).
@@ -188,6 +196,85 @@ for an empty default.
.TP
.B $?
The exit status of the last command.
.SS Parameter expansion
.TP
.B ${#VAR}
The length of the value in characters.
.TP
.BR ${VAR#\fIpattern\fP} ", " ${VAR##\fIpattern\fP}
The value without the shortest (longest) prefix matching
.IR pattern .
.TP
.BR ${VAR%\fIpattern\fP} ", " ${VAR%%\fIpattern\fP}
The value without the shortest (longest) suffix matching
.IR pattern .
.TP
.BR ${VAR/\fIpattern\fP/\fIstring\fP} ", " ${VAR//\fIpattern\fP/\fIstring\fP}
The value with the first (every) longest match of
.I pattern
replaced by
.IR string ;
.B /#
and
.B /%
only match at the start and at the end.
.TP
.BR ${VAR:\fIoffset\fP} ", " ${VAR:\fIoffset\fP:\fIlength\fP}
A substring; offset and length are arithmetic expressions, negative values
count from the end.
.TP
.BR ${VAR:\-\fIword\fP} ", " ${VAR:=\fIword\fP} ", " ${VAR:+\fIword\fP} ", " ${VAR:?\fIword\fP}
.I word
if
.B VAR
is unset or empty (and assign it with
.BR := ),
.I word
if it is set and not empty, or an error with the message
.IR word .
Without the colon, only an unset variable counts.
.PP
The word is expanded but not split. In patterns,
.BR * ,
.B ?
and
.B [...]
are wildcards that also match
.BR / ;
quoted characters and values of variables match literally.
.SS Arithmetic expansion
.B $((\fIexpression\fP))
is replaced by the value of
.IR expression ,
computed with 64-bit integers. The operators of C are supported,
in order of precedence:
.BR "++ \-\-" ,
unary
.BR "+ \- ! ~" ,
.B **
(power),
.BR "* / %" ,
.BR "+ \-" ,
.BR "<< >>" ,
.BR "< <= > >=" ,
.BR "== !=" ,
.BR & ,
.BR ^ ,
.BR | ,
.BR && ,
.BR || ,
.BR "? :" ,
the assignments
.B = += \-= *= /= %= <<= >>= &= ^= |=
and
.BR , .
Variables can be used with or without
.BR $ ;
an unset variable is an error, an empty one is 0. Numbers can be
hexadecimal
.RB ( 0x1F )
or octal
.RB ( 017 ).
.SS Positional parameters
.TP
.B $0
@@ -219,6 +306,9 @@ All positional parameters as one word, separated by blanks.
.TP
.B $$
The process ID of the shell.
.TP
.B $!
The process ID of the last background job.
.SS Command substitution
.B $(\fIcommand\fP)
is replaced by the output of
@@ -226,7 +316,7 @@ is replaced by the output of
which runs in a subshell. Trailing newlines are removed. Unquoted, the
output is split into words at blanks and newlines; inside double quotes it
stays one word. Wildcards and operators in the output are not interpreted.
Backticks and arithmetic expansion are not supported.
Backticks are not supported.
.SS Tilde and brace expansion
.B ~
and
@@ -444,8 +534,39 @@ Exit the shell with status
.BI set " VAR" = value
Set a variable.
.TP
.BR "set \-\-" " [\fIargs\fP ...]"
Set the positional parameters.
.BR set " [\fB\-+ex\fP] [\fB\-+o\fP \fIoption\fP] [\fB\-\-\fP] [\fIargs\fP ...]"
Set
.RB ( \- )
or unset
.RB ( + )
options and set the positional parameters to
.IR args .
.B \-e
.RB ( errexit )
exits the shell when a command fails, except in conditions of
.BR if ,
.B while
and
.BR until ,
negated commands and all but the last command of
.B &&
and
.B ||
lists.
.B \-x
.RB ( xtrace )
prints every simple command after expansion.
.B \-o pipefail
makes the status of a pipeline the one of the last command that failed.
.B \-u
.RB ( nounset )
is always on.
.B set \-o
and
.B set +o
show the options,
.B set
without arguments shows the variables.
.TP
.BI export " VAR" = value
Export a variable.
@@ -473,9 +594,13 @@ Continue stopped job
.I n
in the background.
.TP
.BR wait " [\fB%\fP\fIn\fP]"
.BR wait " [\fB%\fP\fIn\fP | \fIpid\fP]"
Wait for job
.I n
.IR n ,
the job with process
.I pid
(e.g.
.BR $! ),
or for all background jobs.
.TP
.BR alias " [\fIname\fP[\fB=\fP\fIvalue\fP] ...]"
@@ -525,6 +650,48 @@ prints
.I prompt
if the input is a terminal. The exit status is 1 at the end of the input.
.TP
.BR eval " [\fIargs\fP ...]"
Join the arguments with blanks and run the result as a command in the
current shell.
.TP
.BR exec " [\fIcommand\fP [\fIargs\fP ...]]"
Replace the shell with
.IR command .
Without a command, the redirections of
.B exec
apply to the shell itself
.RB ( "exec > log 2>&1" ).
.TP
.BR trap " [\fB\-lp\fP] [[\fIaction\fP] \fIsignal\fP ...]"
Run
.I action
in the shell when
.I signal
arrives (after the running command) or, for
.B EXIT
.RB ( 0 ),
when the shell exits; a script with an EXIT trap also runs it when it is
ended by SIGINT, SIGTERM or SIGHUP. Signals:
.BR HUP ,
.BR INT ,
.BR QUIT ,
.BR TERM ,
.BR USR1 ,
.BR USR2 ,
.BR ALRM ,
.BR WINCH .
An empty
.I action
ignores the signal (also in started programs),
.B \-
restores the default.
.B trap
and
.B trap \-p
show the traps,
.B trap \-l
the signals.
.TP
.B help
Show a summary of builtins and features.
.SH JOB CONTROL
@@ -662,6 +829,8 @@ make > build.log 2>&1 || echo "failed: $?"
LANG=C sort file
alias ll=\(aqls \-l\(aq
greet() { echo "Hello ${1:\-World}"; }
set \-euo pipefail; trap \(aqrm \-rf "$tmp"\(aq EXIT
echo ${file##*/} $((n + 1))
git ls\-files | while read \-r f; do wc \-l "$f"; done
while read \-r user rest; do echo "$user"; done < /etc/passwd
(cd build && make) > build.log 2>&1