It seems to mainly exist as an equivalent to the C idiom ++argv; --argc; which is (given the benefit of >30 years of hindsight since C89) a complicating and not very readable way to save memory processing arguments.
Its definition in POSIX makes it unintuitive for shell scripters. Emma should elaborate here when fae has time, fae has more experience with this.
It necessitates storing "$0" as a new shell variable to be able to continue using it, which shell authors writing diagnostics messages and following good practice always want to do.
It's inflexible; it can only be used for the one task of shifting through arguments.
shift is the only real way to iterate over arguments ($1, $2, $3...) in shell. Particularly with the following idiom:
argv0="$0"# save $0whiletest -n "$1"# while there is a remaining argument to usedoprintf'%s argument: %s\n'"$argv0""$1"# example useshift# <--- boo!done
What if variables could hold the names of other variables? Not like pointers in C but simply:
foo = 5;
# 5 is a string; this is still stringly typed like sh
bar = foo;
out "$[bar]";
# out means echo (no options allowed)
# the [square brackets] mean expand what is inside bar
# and then use that variable
# $[bar] becomes
# $foo because bar == "foo"
This could be used for better argument usage:
seq 1 $# \
| for i { out "$0 argument: $[i]" }
for in this example is a shell built-in that, for each line in standard input, sets the given variable (in this case i) to that line's content before running the commands in the curly braces. seq(1) in this usage prints a new-line delimited list of integers in the sequence described in its arguments. out is an analogue to echo(1) as currently being described in #27.
This might be a terrible idea that can be used to write terrible scripts. Also, there is no real concept of betta(1) yet, so I'm basing my examples off sh(1p).
I don't like the shell built-in `shift`.
- It seems to mainly exist as an equivalent to the C idiom `++argv; --argc;` which is (given the benefit of >30 years of hindsight since C89) a complicating and not very readable way to save memory processing arguments.
- Its definition in POSIX makes it unintuitive for shell scripters. Emma should elaborate here when fae has time, fae has more experience with this.
- It necessitates storing `"$0"` as a new shell variable to be able to continue using it, which shell authors writing diagnostics messages and following good practice always want to do.
- It's inflexible; it can only be used for the one task of shifting through arguments.
`shift` is the only real way to iterate over arguments (`$1`, `$2`, `$3`...) in shell. Particularly with the following idiom:
```sh
argv0="$0" # save $0
while test -n "$1" # while there is a remaining argument to use
do
printf '%s argument: %s\n' "$argv0" "$1" # example use
shift # <--- boo!
done
```
What if variables could hold the names of other variables? Not like pointers in C but simply:
```
foo = 5;
# 5 is a string; this is still stringly typed like sh
bar = foo;
out "$[bar]";
# out means echo (no options allowed)
# the [square brackets] mean expand what is inside bar
# and then use that variable
# $[bar] becomes
# $foo because bar == "foo"
```
This could be used for better argument usage:
```
seq 1 $# \
| for i { out "$0 argument: $[i]" }
```
`for` in this example is a shell built-in that, for each line in standard input, sets the given variable (in this case `i`) to that line's content before running the commands in the curly braces. [seq(1)](https://www.man7.org/linux/man-pages/man1/seq.1.html) in this usage prints a new-line delimited list of integers in the sequence described in its arguments. `out` is an analogue to echo(1) as currently being described in #27.
This might be a terrible idea that can be used to write terrible scripts. Also, there is no real concept of betta(1) yet, so I'm basing my examples off sh(1p).
_Originally posted by @trinity in https://git.tebibyte.media/bonsai/harakit/issues/8#issuecomment-2873_
It necessitates storing "$0" as a new shell variable to be able to continue using it, which shell authors writing diagnostics messages and following good practice always want to do.
shift(1) does not modify the value of $0, actually. From shift(1p):
DESCRIPTION
The positional parameters shall be shifted. Positional parameter 1
shall be assigned the value of parameter (1+n), parameter 2 shall be
assigned the value of parameter (2+n), and so on. The parameters
represented by the numbers "$#" down to "$#-n+1" shall be unset, and
the parameter '#' is updated to reflect the new number of positional
parameters.
The value n shall be an unsigned decimal integer less than or equal to
the value of the special parameter '#'. If n is not given, it shall be
assumed to be 1. If n is 0, the positional and special parameters are
not changed.
> It necessitates storing "$0" as a new shell variable to be able to continue using it, which shell authors writing diagnostics messages and following good practice always want to do.
shift(1) does not modify the value of `$0`, actually. From shift(1p):
```
DESCRIPTION
The positional parameters shall be shifted. Positional parameter 1
shall be assigned the value of parameter (1+n), parameter 2 shall be
assigned the value of parameter (2+n), and so on. The parameters
represented by the numbers "$#" down to "$#-n+1" shall be unset, and
the parameter '#' is updated to reflect the new number of positional
parameters.
The value n shall be an unsigned decimal integer less than or equal to
the value of the special parameter '#'. If n is not given, it shall be
assumed to be 1. If n is 0, the positional and special parameters are
not changed.
```
_Originally posted by @emma in https://git.tebibyte.media/bonsai/harakit/issues/8#issuecomment-2875_
Its definition in POSIX makes it unintuitive for shell scripters. Emma should elaborate here when fae has time, fae has more experience with this.
From: "Lawrence Velázquez" <vq@larryv.me> To: "Christoph Anton Mitterer" <calestyo@scientia.org>, "Emma Tebibyte" <emma@tebibyte.media>
Cc: <dash@vger.kernel.org> Bcc:
Date: 2023-12-06 10:29 PM
Subject: Re:
On Thu, Dec 7, 2023, at 12:00 AM, Christoph Anton Mitterer wrote:
> On Wed, 2023-12-06 at 21:40 -0700, Emma Tebibyte wrote:
>> I found a bug in dash version 0.5.12 where when shifting more than
>> ?#,
>> the shell exits before evaluating a logical OR operator.
>
> AFAIU from POSIX this is perfectly valid behaviour:
>
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#shift
>
>> EXIT STATUS
>> If the n operand is invalid or is greater than "$#", this may be
>> considered a syntax error and a non-interactive shell may exit; if
>> the shell does not exit in this case, a non-zero exit status shall
>> be returned. Otherwise, zero shall be returned.
See also Section 2.8.1 [*], which states that interactive shells
shall not exit on special built-in utility errors and that:
In all of the cases shown in the table where an interactive
shell is required not to exit, the shell shall not perform
any further processing of the command in which the error
occurred.
[*] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_01
--
vq
> Its definition in POSIX makes it unintuitive for shell scripters. Emma should elaborate here when fae has time, fae has more experience with this.
```
From: "Lawrence Velázquez" <vq@larryv.me> To: "Christoph Anton Mitterer" <calestyo@scientia.org>, "Emma Tebibyte" <emma@tebibyte.media>
Cc: <dash@vger.kernel.org> Bcc:
Date: 2023-12-06 10:29 PM
Subject: Re:
On Thu, Dec 7, 2023, at 12:00 AM, Christoph Anton Mitterer wrote:
> On Wed, 2023-12-06 at 21:40 -0700, Emma Tebibyte wrote:
>> I found a bug in dash version 0.5.12 where when shifting more than
>> ?#,
>> the shell exits before evaluating a logical OR operator.
>
> AFAIU from POSIX this is perfectly valid behaviour:
>
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#shift
>
>> EXIT STATUS
>> If the n operand is invalid or is greater than "$#", this may be
>> considered a syntax error and a non-interactive shell may exit; if
>> the shell does not exit in this case, a non-zero exit status shall
>> be returned. Otherwise, zero shall be returned.
See also Section 2.8.1 [*], which states that interactive shells
shall not exit on special built-in utility errors and that:
In all of the cases shown in the table where an interactive
shell is required not to exit, the shell shall not perform
any further processing of the command in which the error
occurred.
[*] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_01
--
vq
```
_Originally posted by @emma in https://git.tebibyte.media/bonsai/harakit/issues/8#issuecomment-2877_
The only built-in commands I see as absolutely necessary are let (or a way to change the shell environment; see #152) and cd or chdir.
The argument that built-ins drastically speed up shell scripts by avoiding the overhead of spawning a new process is fair but doesn't sway me as built-ins are often a great source of confusion (echo -n foo and $(command -v foo) disagreeing is always weird).
The only built-in commands I see as absolutely necessary are `let` (or a way to change the shell environment; see #152) and `cd` or `chdir`.
The argument that built-ins drastically speed up shell scripts by avoiding the overhead of spawning a new process is fair but doesn't sway me as built-ins are often a great source of confusion (`echo -n foo` and `$(command -v foo)` disagreeing is always weird).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
I don't like the shell built-in
shift.It seems to mainly exist as an equivalent to the C idiom
++argv; --argc;which is (given the benefit of >30 years of hindsight since C89) a complicating and not very readable way to save memory processing arguments.Its definition in POSIX makes it unintuitive for shell scripters. Emma should elaborate here when fae has time, fae has more experience with this.
It necessitates storing
"$0"as a new shell variable to be able to continue using it, which shell authors writing diagnostics messages and following good practice always want to do.It's inflexible; it can only be used for the one task of shifting through arguments.
shiftis the only real way to iterate over arguments ($1,$2,$3...) in shell. Particularly with the following idiom:What if variables could hold the names of other variables? Not like pointers in C but simply:
This could be used for better argument usage:
forin this example is a shell built-in that, for each line in standard input, sets the given variable (in this casei) to that line's content before running the commands in the curly braces. seq(1) in this usage prints a new-line delimited list of integers in the sequence described in its arguments.outis an analogue to echo(1) as currently being described in #27.This might be a terrible idea that can be used to write terrible scripts. Also, there is no real concept of betta(1) yet, so I'm basing my examples off sh(1p).
Originally posted by @trinity in #8 (comment)
shift(1) does not modify the value of
$0, actually. From shift(1p):Originally posted by @emma in #8 (comment)
Originally posted by @emma in #8 (comment)
The only built-in commands I see as absolutely necessary are
let(or a way to change the shell environment; see #152) andcdorchdir.The argument that built-ins drastically speed up shell scripts by avoiding the overhead of spawning a new process is fair but doesn't sway me as built-ins are often a great source of confusion (
echo -n fooand$(command -v foo)disagreeing is always weird).