Shell What is the best practice to learn SHELL/BASH

eval a_${i}=\$l
Using the symbol table to simulate an array is definitely creative.
I used to do this back in the 1980s when the Bourne shell was all actually written by Steve Bourne (and there few other good shells around).
But each one of those evals causes a fork(2) and exec(2), so there is something of an issue with execution speed...
 
awk is still a lot more powerful than shell but i find shell more readable
it would be nice if posix adopted/had bash ${::} and ${//} expansions for substring and replace
you can emulate them with sed/awk but i don't like to spawn external programs if not really necessary
 
awk is still a lot more powerful than shell but i find shell more readable
it would be nice if posix adopted/had bash ${::} and ${//} expansions for substring and replace
you can emulate them with sed/awk but i don't like to spawn external programs if not really necessary
Interesting. Thank you. I'm old-skool so may I ask, where can I find a tutorial for your approach?

Your script appears to be much faster too. And terse. Being familiar to me, awk is fairly easy for me to read, but one of the reasons I dislike using awk is because it can really slow things down a lot:

$ time myscript
...
0.013u 0.013s 0:00.04 50.0% 212+276k 1+0io 0pf+0w
$ time yourscript
...
0.002u 0.000s 0:00.00 0.0% 0+0k 0+0io 0pf+0w
 
well I just learned by investigating different scripts and researched/kept what i liked
can't point you to a book or document
also for such short scripts is not very relevant to measure time and your script is dragged back by several forks / execs of awk
but one rule i try to follow loosely is to minimize the external commands / forks /execs
eg i taught myself to always do find /somehwere something |xargs command instead of find /somewhere something -exec command
 
For these kind of simple scripts i don't use sh nor c, I tend to switch to a language like ruby,python,crystal,nim. Where portability being an option not a requirement.
Scheme program below prints a file and line-numbers,
Code:
#lang racket
(let ([t 0])
    (for ([line (file->lines "file.txt")])
        (set! t (+ t 1))
        (display (format "~v:" t))
        (displayln line))
)
 
just to clarify for the OP, sh does not support arrays.
But each one of those evals causes a fork(2) and exec(2), so there is something of an issue with execution speed...


You are correct. I have just suggested a kludge, to help the OP; temporarily. There's a lot of problems with that snippet, e.g. it can handle " and $, but
if there is a whitespace in a filenames in the list, there's a problem. Also, AFIAK array as a data structure is stored in consecutive addresses in memory.
I'm not sure how shell handles those iterations either, in terms of memory addr. The point on fork(2) & execve(2) is also correct. I've tested it on a 10k
records of filenames to check and to see how the printf utility handles the %* format specification. The performance was an issue which was expected.
That is why I think if you can't solve it with C and/or shell (+ awk, sed etc) then you have to use Perl. It fills the gap between C and shell/base (sed etc).
By the way, the Perl 7 is coming very soon. It's going to be the death knell for all other scripting languages IM(not-so)HO. I love to see python is dead!
 
... Perl. It fills the gap between C and shell/base (sed etc).
For many years, my policy was that a task that could not be scripted easily in Bourne shell should be written in perl(1).
I worked on a lot of different Unix variants, and each shell was just a little bit different. But Bourne shell and perl were constants.
I still think that way. CPAN is a fabulous resource.

[I am, unfortunately, old enough to know what Bourne shell is, and that's not such a common skill these days.]
 
I still think that way. CPAN is a fabulous resource.

That's correct. All fun things start with CPAN. People are whining about perl because:
1. They start to learn it.
2. Scalar, list, array, hash, subroutine, basic I/O and control structure ... COOL! It was easy.
3. Regex... Oops!
4. Meh! It's hard, old and I hate it.
5. They never reach to the point of learning Modules and CPAN, i.e. the real fun parts.
6. Still, the problem is there, i.e. Regex. But now, with python for example, they can copy/paste from the Stackoverflow.
 
Could I ask you about the reasons for that?
Python is more popular these days. There are now a lot more people that know how to read and write Python code than Perl. I started coding in Perl about 20 years ago and used it a lot in the early '00s. Still like the language but I won't recommend it for a first language to learn. It has a rather loose syntax which will inevitably lead to bad programming habits that are difficult to unlearn. First language I learned was good old BASIC back in the '80s on the Commodore 64. Then assembler (6502, 680x0, 6809 and some 8051). At school we were taught Pascal (that was the number one language at that time). I can read and understand C/C++ but writing it from scratch is still somewhat problematic (I don't use it enough, so I simply don't have the experience).

Learn how to split up a large complex problem into smaller, easier to solve chunks. Understand how conditions work (if .. then .. else) and how to do loops (while ..., for ...) and you can basically program in any language. Learn one language and it'll be easy to learn a second, third and so on.
 
For many years, my policy was that a task that could not be scripted easily in Bourne shell should be written in perl(1).
I worked on a lot of different Unix variants, and each shell was just a little bit different. But Bourne shell and perl were constants.
I still think that way. CPAN is a fabulous resource.

[I am, unfortunately, old enough to know what Bourne shell is, and that's not such a common skill these days.]
In what cases it was perl instead of bash?
 
In what cases it was perl instead of bash?
When you have to handle more complex data structures (like the earlier mentioned arrays). Shell scripting is meant to string a couple of system commands together, it's not meant to deal with complex data. While you can certainly coax a shell script into doing some complex things, it tends to get unwieldy making the code difficult to understand and debug in case of problems.
 
You are correct. I have just suggested a kludge, to help the OP; temporarily. There's a lot of problems with that snippet, e.g. it can handle " and $, but
if there is a whitespace in a filenames in the list, there's a problem. Also, AFIAK array as a data structure is stored in consecutive addresses in memory.
I'm not sure how shell handles those iterations either, in terms of memory addr. The point on fork(2) & execve(2) is also correct. I've tested it on a 10k
records of filenames to check and to see how the printf utility handles the %* format specification. The performance was an issue which was expected.
That is why I think if you can't solve it with C and/or shell (+ awk, sed etc) then you have to use Perl. It fills the gap between C and shell/base (sed etc).
By the way, the Perl 7 is coming very soon. It's going to be the death knell for all other scripting languages IM(not-so)HO. I love to see python is dead!
Hope It will be backward compatible. Saw a bunch of PHP that don't work in new versions, the code becomes thrash, couse it wont work on new versions anymore.
 
sh: sh(1) is close to the POSIX.1".
php: at the moment stick to the php 7.4. There's nothing notable in the php 8
I mean that php app from 5.x version won't run on php 7.x. I though that same thing are happening evrywhere except assembler.
 
I often use simple lists and awk to simulate array-like structures in sh(1) -- a simple example:
Code:
#!/bin/sh
list="a b c d e foo g"
listcount=$(echo $list | awk 'BEGIN{FS=" "}{print NF}')
echo 'List="'$list'"'
echo "Element count="$listcount
echo "A random element access:"
el=$(echo $list | awk 'BEGIN{FS=" "}{print $6}')
echo "Element 6 = "$el
echo "Iteration:"
i=0; for x in $list; do
  i=$(($i+1))
  echo "Element "$i" = "$(echo $list | awk 'BEGIN{FS=" "}{print $'$i'}')
done

You can also use wc(1) to count elements:

Code:
% list="a b c d e foo g"

% echo $list
a b c d e foo g

% echo $list | wc
       1       7      16

% echo $list | wc -w
       7

% echo $list | wc -w | tr -cd '0-9'
7
 
I mean that php app from 5.x version won't run on php 7.x.
Only if you used specific functions. Most of the PHP 5 code will run just fine on 7.

I though that same thing are happening evrywhere except assembler.
No, not really. Well, most of the time anyway. There's definitely a few major hurdles when switching from Python 2.x to 3.x. Other languages have similar issues from time to time. Heck, even assembler is prone to this (compare protected mode, real mode and 64 bit on the x86 for example).
 
In what cases it was perl instead of bash?
Bourne shell is not bash(1).
Bourne shell was written by Stephen R. Boune, and was introduced in V7 Unix in 1979, as /bin/sh.
Every /bin/sh, on every Unix and Linux variant since, has been backwards compatible with the Bourne shell.
Many modern shells (bash, dash, ksh, pdksh, zsh, ...) trace their foundation back to Bourne shell. All of them, inevitably, offer more "features" than Bourne shell.
Bash was written by Brian Fox for the GNU Project as a free software replacement for the Bourne shell in 1989. It has more bells, whistles, and fandangles than most.

For power, speed, and capability, perl(1) is probably an order of magnitude more powerful than any of the shells.
 
Please, give an examples of: duplicate stdin,
[n1]<&n2 duplicate stdin (or file descriptor n1) from file
descriptor n2
can't get a poin
 
Hope It will be backward compatible. Saw a bunch of PHP that don't work in new versions, the code becomes thrash, couse it wont work on new versions anymore.
I was able to upgrade all my thousands of lines of old PHP 5 code to PHP 7 a few years back without too much effort, maybe spending 1 or 2 days total on it. A lot of the required changes are very similar, so solving a problem in one place usually leads to solving similar problems in several other places. All the sub-version upgrades, from 7.0 to 7.1 to 7.2, etc., have gone smoothly with very few changes.

/bin/sh is one of the most backwards-compatible languages I've ever used, which is a very big reason why I use it so much.
Correct. The original Bourne shell was sh, and BASH is just a rough acronym for "(B)ourne-(A)gain (SH)ell.
 
Code:
#!/bin/sh
exec 3</etc/passwd
exec 4</etc/group
while read a<&3
do
echo user ${a%%:*}
read b<&4
echo group ${b%%:*}
done
 
Back
Top