Sujet : Re: a sed question
De : nn.throttle (at) *nospam* xoxy.net (Helmut Waitzmann)
Groupes : comp.unix.shellDate : 21. Dec 2024, 19:20:20
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <83wmfsj3tn.fsf@helmutwaitzmann.news.arcor.de>
References : 1 2 3
User-Agent : Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)
Salvador Mirzo <
smirzo@example.com>:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>
On 18.12.2024 20:46, Salvador Mirzo wrote:
>
First (before I forget it) change your string comparison '<' to the
numerical comparison operator '-lt' as in: test $# -lt 2 && usage
Otherwise, if you get used to using the wrong operator, you may get
subtle errors in future if you continue that habit.
>
Changed. Why is it the wrong operator?
'<' compares two strings lexically, whereas '-lt' compares two numbers numerically. Some examples:
1 < 2 ==> true
2 < 2 ==> false
3 < 2 ==> false
10 < 2 ==> true, probably not your intention.
1 -lt 2 ==> true
2 -lt 2 ==> false
3 -lt 2 ==> false
10 -lt 2 ==> false
It seems it's not the standard one---checking just now on the
POSIX.1 spec.
The recent POSIX standard knows of the '<' operator, see
<
https://pubs.opengroup.org/onlinepubs/9799919799/utilities/test.html#tag_20_121_05>.
Also note that using $* may not work correctly (e.g. depending on
filenames [containing spaces] used). The safe form is a quoted "$@"
>
I learned something here.
>
--8<-------------------------------------------------------->8---
$ cat script.sh
#!/bin/sh
echo dollar-star $*
./script dollar-star $*
>
echo quoted-dollar-star "$*"
./script "$*"
>
echo dollar-at $@
./script $@
>
echo quoted-dollar-at "$@"
./script "$@"
>
$ cat script.c
#include <stdio.h>
>
int main(int argc, char *argv[]) {
printf("\nfull cmdline: ");
for (int i = 0; i < argc; ++i) {
printf("%s ", argv[i]);
}
printf("\nargs: %d\n", argc);
for (int i = 0; i < argc; ++i) {
printf("arg %d: %s\n", i, argv[i]);
}
return 0;
}
--8<-------------------------------------------------------->8---
>
$ ./script.sh 1 2 "th ree"
dollar-star 1 2 th ree
>
full cmdline: ./script dollar-star 1 2 th ree
args: 6
arg 0: ./script
arg 1: dollar-star
arg 2: 1
arg 3: 2
arg 4: th
arg 5: ree
quoted-dollar-star 1 2 th ree
>
full cmdline: ./script 1 2 th ree
args: 2
arg 0: ./script
arg 1: 1 2 th ree
dollar-at 1 2 th ree
>
full cmdline: ./script 1 2 th ree
args: 5
arg 0: ./script
arg 1: 1
arg 2: 2
arg 3: th
arg 4: ree
quoted-dollar-at 1 2 th ree
>
full cmdline: ./script 1 2 th ree
args: 4
arg 0: ./script
arg 1: 1
arg 2: 2
arg 3: th ree
$
So using "$@" is the only way to have the shell pass its positional parameters unmodified (i. e. neither glued together nor split at internal white space (more precise: split according to the contents of the IFS shell parameter)) to commands it invokes.