Live data from Hacker News

Pure Bash Bible

github.com

181–190 of 258 posts

Re: Pure Bash Bible

#181

Earlier quoted context omitted.

I have a personal dislike for "non human readable" used as shorthand for "not immediately and easily readable by me".

The human part is a hyperbole. "This code is unreadable" implies "This code is unreadable for the intended audience." Here's how I'd write that function: trim_string() { python3 -c 'import sys; sys.stdout.write(sys.argv[1].strip())' "$1" }

"A collection of pure bash alternatives to external processes."

Re: Pure Bash Bible

#182

Earlier quoted context omitted.

I think the point is that it takes a lot longer pick the syntax up compared to some if/then/for/loop version of trim even if that would be way more verbose.

Yes, but I think that's antithetical to what languages like bash and perl are trying to do. Someone well versed in the language can do some pretty complex operations in a few keystrokes.

which gets back to the original point that these languages have chosen to be more powerful over being more immediately readable. you have to know many more features of the language to understand what is going on compared to colloquially used constructs like if/then or for loops. If you understand english you are a lot closer to understanding the latter rather than the former, more domain specific syntax.

Re: Pure Bash Bible

#183

Earlier quoted context omitted.

Maybe "unreadable" and "readable" aren't the best ways to approach this conversation. It's certainly less readable than, say, my_str.strip()

Are you comparing a call to a definition? `trim_string "$my_str"` is no less readable than `my_str.strip()`.

I mean, I would say it is. Why are there quotes around the variable? What happens when I remove the quotes?

The quotes don't function like the parens. If this were a two argument function, you wouldn't put one pair of quotes around the whole thing. They're clearly transforming the variable somehow, but I'm not sure how and/or why they're necessary.

Re: Pure Bash Bible

#184

Earlier quoted context omitted.

> Perl is probably the closest but still has some warts related to redirection. I wholehartedly agree on perl but can you expand on the redirection warts? I seldom had problems with perls' FHs, while, on the contrary I seem to be unable to wrap my head around the contorted syntax involved in bash's handling of descriptors - especially when more than 2 handles are involved.

Well -- I was comparing Perl to Python in this case. There is roughly the same amount of boilerplate and both are easier to read than bash's redirection. The wart is that you need IPC::Open3 or equivalent because Perl's intrinsics can not synthesize the pipe operator (though you will think that they can) if you need to insert yourself into the middle of a chain of commands. Nowadays there are decent wrappers for call…

Aw, right. I'd forgotten about IPC::Open3. Because I did not want to think about it, mostly (and so, I usually do exactly what you say people do :-) )

Re: Pure Bash Bible

#185
post #168

Earlier quoted context omitted.

> That's not as easy as > cat something | grep "this" | cut -f 1 | sed -e 's/.../.../' Literally none of this is actually useful if you're already in Python: ( line.split('\t')[0].replace(…, …) for line in open('something') if 'this' in line ) > You end up writing too much code I can believe that if you're calling to external processes to perform operations which are pretty much trivial in the language.

Of course, if you plan to use one $language alone, you can do anything in that $language. This question is specific to pipes.

> Of course, if you plan to use one $language alone, you can do anything in that $language.

That's missing what I'm noting though, which is that you don't need pipes anywhere near a shell script if you can simply do more of your work in-language. Case in point being that the entire pipeline you cited as an issue has no reason to exist outside of a shell or shell script.

Re: Pure Bash Bible

#186

Earlier quoted context omitted.

The slow down caused to any developer that has to try and read that is probably orders of magnitude more worth optimizing for than how fast a bath script runs. I'll take the grep/sed/awk version.

Not defending this particular example, but there are contexts where avoiding an external call can make a difference. Think a script calling an external program in a deeply nested loop. This sort of optimization could be used as a last resort, after identifying a real performance issue and evaluating the possibility of restructuring the code.

I've ran into this decades ago with file servers back. Half a million files, takes too long to do a simple for loop and calling 3rd party processes for awk/sed when I was just using them to format/search text. Breaking it down to just to mosty bash one scripts reduced the run time and ended all pauses.

Re: Pure Bash Bible

#189
post #157

This seems like a good time to mention my (ridiculous) project, a ctypes module for bash. https://github.com/taviso/ctypes.sh/wiki There are some little demos here: https://github.com/taviso/ctypes.sh/tree/master/test I even ported the GTK+3 Hello World to bash as a demo: https://github.com/taviso/ctypes.sh/blob/master/test/gtk.sh

I found ctypes.sh to be legitimately useful for managing resources in nix-shell.

E.g. flock a lock file and set CLOEXEC so that subprocesses don't hold the lock open after the shell exits.

E.g. Use memfd_create to create a temp file and write a key. Then pass /proc/$$/fd/$FD to programs that need the key as a file. When the shell exits, the file can no longer be opened.

You can do similar things with traps, but they aren't guaranteed to execute, whereas these OS primitives will always be cleaned up.

Re: Pure Bash Bible

#190

I have a personal dislike for regexes and non human readable code, it gives maintenance headache. It's why I avoid shell scripts as much as possible. The first example is not human readable, if the name of the function is a lie, I have no idea what this piece of code do : trim_string() { : "${1#"${1%%[![:space:]]*}"}" : "${_%"${_##*[![:space:]]}"}" printf '%s\n' "$_" }

Is the following a maintenance headache, or non-human readable? #!/bin/sh FOO=" some long string here " FOO="$( echo "$FOO" | sed -e ' s/^[[:space:]]//g; s/[[:space:]]$//g ' )" This isn't "pure bash", but most of what I write in shell scripts isn't "pure bash". It's shell scripting: dirty, slow, easy, effective. Like any 'language', it takes on the complexity you put into it. English is really complicated, but you ca…

> echo "$FOO" | sed -e ' s/^[[:space:]]//g; s/[[:space:]]$//g '

Your example fails when $FOO is "-n", for instance. Also the g modifiers are redundant in your example since there's only one beginning of line per line and one end of line per line.

I would instead write this:

  sed -r 's/^\s+|\s+$//g' 
EDIT: I think I see now what you probably thought would happen by using g, but no it wouldn't remove multiple spaces. So, you example also fails when $FOO is " x" (using 2 or more spaces at the ends).
Post reply on HN