Tiny Core Linux
General TC => Programming & Scripting - Unofficial => Topic started by: nick65go on February 25, 2023, 05:25:01 AM
-
Hi, sorry for maybe a novice question.
I would like to typically define the main logic prior to defining its inner sub-functions, so someone reading the code will focus on the main logic first. Often this takes the form of creating a "main" function at the top of the file, and invoking it at the bottom. I mean just write code from top-to-bottom, sprinkling in functions as needed at the bottom, after main code/function exit?
Is there any lost speed in sh-type scripts like these? Or any memory issues not-initialized variables?
-
Should be fine to write like that.
-
Hi nick65go
I think I tried something similar but received errors because I was
trying to call functions before they were defined. You can get
around this by sourcing a file containing your functions at the
top of your script.
-
Hi, nick65go and Rich. Sure it's possible to define a main function at the top of a shell script followed by ancillary functions!
The shell reads shell scripts from top to bottom. If you call the main function at the bottom of the script, at that point the shell will have seen all the function definitions. Try this trivial example--call it HardcodedGreetings.sh:
#!/bin/sh
main()
{
say_hi
say_bye
}
say_hi()
{
echo "hi"
}
say_bye()
{
echo "bye"
}
main
The script works exactly as expected:
$ ./HardcodedGreetings.sh
hi
bye
If the script has arguments, you need to remember to pass the script's arguments to the main function. Here is a trivial example to illustrate this--let's call this one CustomGreeting.sh:
#!/bin/sh
main()
{
say_arguments "$@"
}
say_arguments()
{
echo "$@"
}
main "$@"
Again, it works exactly as expected:
$ ./CustomGreeting.sh testing 1 2 3
testing 1 2 3
-
@GNUser: Thanks, very good that you gave the examples. Also good that there is no penalty in execution speed.
-
Hi GNUser
Well done, thank you. :)
-
Hi Rich. You're welcome. It's rare that the help flows in that direction :)
Hi nick65go. You're welcome. Glad I could help. Actually, here's a better example of CustomGreeting.sh that shows what's going on a bit more clearly:
#!/bin/sh
main()
{
say_hi "$1"
say_bye "$2"
}
say_hi()
{
echo "hi $1"
}
say_bye()
{
echo "bye $1"
}
main "$@"
$ ./CustomGreeting.sh "John" "Mr. John Doe"
hi John
bye Mr. John DoeHappy Hacking!
-
#!/bin/sh
main()
{
say_hi "$1"
say_bye "$2"
}
say_hi()
{
echo "hi $1"
}
say_bye()
{
echo "bye $1"
}
for argx in "${@}" ; do
case $argx in
m|main) shift ; main "${@}" ; exit 0 ;;
# other args
*) return 0 ;;
esac ; done
# no args
[ $# -eq 0 ] && return 0 ;
with the above addition ( worked out in this (messy) topic http://forum.tinycorelinux.net/index.php/topic,26133.msg167895.html )
its possible to source the script to access the functions within shell
which imho can be useful for testing / composing new functions / cases .
-
Hi mocore
... its possible to source the script to access the functions within shell ...
Do you mean the way you can call functions from /etc/init.d/tc-functions from the command line:
tc@E310:~$ echo $MIRROR
tc@E310:~$ getMirror
tc@E310:~$ echo $MIRROR
http://repo.tinycorelinux.net/10.x/x86/tcz
tc@E310:~$
Because it's sourced in ~/.ashrc:
tc@E310:~$ head -n 4 .ashrc
# ~/.ashrc: Executed by SHells.
#
. /etc/init.d/tc-functions
if [ -n "$DISPLAY" ]
tc@E310:~$
-
@rich
>Do you mean the way you can call functions from /etc/init.d/tc-functions from the command line:
yes like that callable in shell via sourcing a script
but while also avoiding calling the "main" function when sourced
id thaught i had not added an example after posting so...
# source & use functions in shell
. ./CustomGreeting.sh
say_hi foobar
# or
./CustomGreeting.sh main ; # call script and run the man function
an example
replacing
> main "$@"
in https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
with
for argx in "${@}" ; do
case $argx in
m|main) shift ; main "${@}" ; exit 0 ;;
# other args
*) return 0 ;;
esac ; done
# no args
[ $# -eq 0 ] && return 0 ;
allows ". source" of the script without ruining main
then functions or function inputs or environment can be tested / altered / ect
-
Hi mocore
You can source right from the command line.
A file containing some functions:
tc@E310:~$ ls -l Sourcing
-rw-rw-r-- 1 tc staff 20 Mar 6 09:31 Sourcing
tc@E310:~$ cat Sourcing
xyzzy()
{
cal $1
}
Mem()
{
free "-mo"
}
Path()
{
echo $PATH
}
tc@E310:~$ No shebang, not executable, no main, just 3 functions.
The commands work after we source the file:
tc@E310:~$ xyzzy
sh: xyzzy: not found
tc@E310:~$ xyzzy apr
sh: xyzzy: not found
tc@E310:~$ Mem
sh: Mem: not found
tc@E310:~$ Path
sh: Path: not found
tc@E310:~$ . ./Sourcing
tc@E310:~$ xyzzy
March 2023
Su Mo Tu We Th Fr Sa
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
tc@E310:~$ xyzzy apr
April 2023
Su Mo Tu We Th Fr Sa
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
tc@E310:~$ Mem
total used free shared buffers cached
Mem: 3028 1477 1551 0 82 574
Swap: 999 0 999
tc@E310:~$ Path
/home/tc/.local/bin:/usr/local/sbin:/usr/local/bin:/apps/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/sysconfig/tcedir/ondemand
tc@E310:~$
-
hi @rich
wrt title : in a script, could I have the main body folowed by its functions at the botom?
you can order functions in the script however you like
the order the of the named blocks in the script should not affect the script execution
unless a function is called before its defined
which will result in error
$script: line $X: $funcname: not found
as mentioned : https://forum.tinycorelinux.net/index.php/topic,26125.msg167737.html#msg167737
the example
adding an optional explicit case to call the main function then exit
and two return cases , one for no arguments and , one for all other args
allows changing script execution path making calling the main function optional
so other functions can be sourced into shell or other scripts
perhaps its considered better to have ?? ( that seams to be the gist of your reply )
lib-foo.sh
and
foo.sh
where foo.sh effectively encapsulates main block
and lib-foo.sh holds the functions to import