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:
1 parent
f66cf538c0
commit
1f507f6562
20 files changed
+2408
-93
No files matched your search
@@ -286,7 +286,16 @@ func (j *job) result() error {
|
||||
for _, p := range j.procs[:len(j.procs)-1] {
|
||||
printError(p.err)
|
||||
}
|
||||
return j.procs[len(j.procs)-1].err
|
||||
last := j.procs[len(j.procs)-1].err
|
||||
if pipefail && exitStatus(last) == 0 {
|
||||
// The status of the last command that failed
|
||||
for i := len(j.procs) - 2; i >= 0; i-- {
|
||||
if err := j.procs[i].err; exitStatus(err) != 0 {
|
||||
return silent(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return last
|
||||
}
|
||||
|
||||
// waitForeground waits for a job in the foreground. If it is stopped, it is
|
||||
@@ -504,9 +513,12 @@ func builtinBg(args []string, stdout io.Writer) error {
|
||||
func builtinWait(args []string) error {
|
||||
jobs := append([]*job(nil), jobTable...)
|
||||
if len(args) > 1 {
|
||||
j, err := findJob("wait", args)
|
||||
if err != nil {
|
||||
return err
|
||||
j := jobByPid(args[1])
|
||||
if j == nil {
|
||||
var err error
|
||||
if j, err = findJob("wait", args); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
jobs = []*job{j}
|
||||
}
|
||||
@@ -523,6 +535,23 @@ func builtinWait(args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// jobByPid returns the job with a process with the ID in spec (wait $!), or
|
||||
// nil.
|
||||
func jobByPid(spec string) *job {
|
||||
pid, err := strconv.Atoi(spec)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, j := range jobTable {
|
||||
for _, p := range j.procs {
|
||||
if p.cmd != nil && p.cmd.Process.Pid == pid {
|
||||
return j
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// exitShell exits the shell, unless there are stopped jobs and the user was
|
||||
// not warned yet (like bash).
|
||||
func exitShell(code int) error {
|
||||
@@ -530,6 +559,8 @@ func exitShell(code int) error {
|
||||
exitWarned = true
|
||||
return errors.New("there are stopped jobs")
|
||||
}
|
||||
lastStatus = code // $? in the EXIT trap
|
||||
runExitTrap()
|
||||
releaseTerminal()
|
||||
os.Exit(code)
|
||||
return nil
|
||||
|
||||
Reference in new issue
Block a user