site  contact  subhomenews

The elegance of Bash/Ash

November 09, 2008 — BarryK
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.

Comments

functions
Username: MU
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.

functions
Username: MU
"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

Nor IE7
Username: disciple
""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...

Add comment button problem
Username: paulh
"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

Posting code
Username: BarryK
"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.

Short and long answers
Username: rarsa
"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"

Oops
Username: rarsa
"Oops, here is the code [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]

a single command
Username: rarsa
"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. [code]sed -n '\:/\w*/\(hd\w*\|sd\w*\|scd\w*\|sr\w*\|mmc\w*\): s:/\w*/\(\w*\).*:\1:p' /proc/mounts[/code] Again, this would not be a benefit of "bash" but the fact that we can use the external command seamlessly.

FYI blog search doesn't work in IE7 either
Username: disciple
""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 :)

bash.diff: suped-up bash
Username: lstandish
"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.)


Tags: woof