The elegance of Bash/Ash

You can write extremely elegant and concise code in Bash/Ash and similar shells. Recently I have been learning Wirbel (a Python look-alike) by translating a small Bash script. This line is typical:

MNTDDEVS="`mount | cut -f 1 -d ' ' | cut -f 3 -d '/' | grep -E '^hd|^sd|^scd|^sr|^mmc' | tr '\n' ' '`"


or, this does the same thing:

MNTDDEVS="`cat /proc/mounts | cut -f 1 -d ' ' | cut -f 3 -d '/' | grep -E '^hd|^sd|^scd|^sr|^mmc' | tr '\n' ' '`"


The above is a very ordinary line of code in a Bash script, however, see what happens if you convert it to Python/Wirbel/FreeBasic! -- and not just by doing a system() call, actually rewrite it using the inbuilt commands and libraries of the language. You could take some liberties and assign to a 'list' datatype or whatever, if that is more appropriate.

I would be interested if anyone can do the translation in a higher-level language, yet have code that appoaches the elegance and conciseness. This is a challenge to any programmers reading this! Perhaps a functional language could do it.

Oh yeah, one thing most important: readability. One important feature of the above code line is that it is very easy to read. When I had a go at rewriting in Wirbel, my code was many lines and also quite obscure to read.

Posted on 9 Nov 2008, 9:12


Comments:

Posted on 9 Nov 2008, 9:52 by MU
functions
you could use selfwritten functions like:

function cat(thefile){



# add here stuff to open a file

return thecontent

}



Then in the code, you could use nested functioncalls.

result = removespaces(cat("/proc/mounts"))

This could simulate tr and cat.



Then run a grep function on result.

Regular expressions are very different in each language, so it makes no sense, to write a general example here.



Mark

PS: the "Add comment" button does not work in Opera 9.61, so I use Firefox now.


Posted on 9 Nov 2008, 10:03 by MU
functions
In Puppybasic, I added such functions to an external file /usr/lib/wxbasicscript/basefunctions.inc

It can be used by:
include "/usr/lib/wxbasicscript/basefunctions.inc"

It has stuff like "readfiletolist(thefile)".
This loads a file into an array.
Then I use functions like "cutleft(thestring , delimiter".
Those are a kind of replacement for "cut".
e.g. cutleftfromright("/usr/bin/test" , "/") would return: "test".

With the functions in that lib, I can reduce the code massively in my programs.

Puppybasic has no regular expressions, so I use "instr" and "replace" instead.
For this reason, the Basic programs look much different from code written for the bash.

Mark


Posted on 9 Nov 2008, 17:32 by disciple
Nor IE7
"PS: the "Add comment" button does not work in Opera 9.61, so I use Firefox now."
No one seemed to notice my report that it didn't work in IE 7 either (at least on the PCs at uni) after the last upgrade.
Although I can't say for certain that it worked before the upgrade...


Posted on 9 Nov 2008, 19:24 by paulh
Add comment button problem
I've been in correspondence with the PPLOG author Federico about this and it comes down to javascript.
(it is also a problem with the search button.)
Using Opera, try editing site settings for this address and switch javascript off.
Not sure what to do in IE6 or FIrefox 2 but I have the same problem in both.
For FF3 Federico suggests onclick="javascript:this.disabled=true"

It doesn't seem to be a problem in seamonkey



Posted on 10 Nov 2008, 8:51 by BarryK
Posting code
MU, if you want to post any code examples here, you can get a code box like my top post by surrounding it with

"code" your-code-here "/code"

...where you replace the " with opening and closing square brackets. That's standard BBCODE, though that particular tag is not given in the menu -- I don't know why Fedekun decided to leave that off the menu.



Posted on 10 Nov 2008, 13:37 by rarsa
Short and long answers
The short answer:
Bash is quite economic syntax wise due to the pipping and seamless use of external commands. (grep, sed, awk, tr...). This adds to the richness of bash itself, makes it beautiful, elegant but also somewhat cryptic to the untrained eye.

Long answer:
Your line of code looks elegant because you are cheating ;). You are using external commands as if they were part of bash. Let's compare apples to apples.

If you create the functions in a high level language, the actual code would be more readable, accessible and maybe as economic. In bash it is a pain to create reusable libraries given the scope of the variables.

Here is an example (which I find more readable). Please just look at the last line as the simpleGrep function could actually be part of a library

"code"
import re

def simpleGrep(fileName, patternStr) :
result = ""
pattern = re.compile(patternStr)
for line in file(fileName) :
matchObject = pattern.match(line)
if matchObject != None :
result = result + matchObject.group(1) + "\n"
return result


MNTDEVS = simpleGrep("/proc/mounts","/\w+/(hd\w*|sd\w*|scd\w*|sr\w*|mmc\w*)").replace("\n"," ")
"/code"




Posted on 10 Nov 2008, 13:39 by rarsa
Oops
Oops, here is the code

import re

def simpleGrep(fileName, patternStr) :
result = ""
pattern = re.compile(patternStr)
for line in file(fileName) :
matchObject = pattern.match(line)
if matchObject != None :
result = result + matchObject.group(1) + "\n"
return result


MNTDEVS = simpleGrep("/proc/mounts","/\w+/(hd\w*|sd\w*|scd\w*|sr\w*|mmc\w*)").replace("\n"," ")




Posted on 10 Nov 2008, 14:28 by rarsa
a single command
Actually in "bash" you can do it with a single command:
Note: I purposely replaced the standard sed delimiter / with : to make it "easier" to read.

sed -n '\:/\w*/\(hd\w*\|sd\w*\|scd\w*\|sr\w*\|mmc\w*\): s:/\w*/\(\w*\).*:\1:p' /proc/mounts


Again, this would not be a benefit of "bash" but the fact that we can use the external command seamlessly.


Posted on 12 Nov 2008, 9:43 by disciple
FYI blog search doesn't work in IE7 either
"No one seemed to notice my report that it didn't work in IE 7 either"
I see the blog search doesn't work in IE7 either :(
It could really do with a feature to search the comments too :)


Posted on 13 Nov 2008, 3:19 by paulh
for disicple:blog search by content
try the "search by content" option


Posted on 15 Nov 2008, 13:38 by lstandish
bash.diff: suped-up bash
Barry, you might want to check this out:

(from http://www.puppylinux.org/wiki/applications/various/bashdiff):



"I've complied it (I added a patch provided by William) and it works great in Puppy



It adds just about 10K to the original bash but greatly extends the power of bash scripting:



- String handling (strcat, strcpy, strlen, strcmp)

- Array handling

- XML parsing: (expat)

- error checking (try-block)

- Calculations (HP syle rpn calculator)

- GTK UI generation (Way better and cleaner than gtkdialog)

Plus many more features"



And from the project page:

"About:

Bash.Diff is a patch against Bash shell. In the main core, it adds the following syntax: {a..b}; ${var|...}; then-else-fi to for/while/until/case statements; try-block with string exception; <<+; and, <<<<. As builtin, it adds the following: sscanf(3), <string.h>, <ctype.h> wrappers; array, regex(3), stack, queue operations; GDBM, SQLite, PostgreSQL, MySQL database interfaces; HTML template engine (BASP); Expat XML parser interface; x-y char plot; DOS, CSV, Awk support; Libwebserver interface; RPN calculator with <math.h> functions; and, GTK+2 interface for GUI dialog."



(By the way, "by content" PPLOG search is not working in Opera 9.6, either.)