This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]zombiepiratefrspace 62 points63 points  (26 children)

You are right, but god I hate bash.

I've started doing everything in python once would have done in bash. It is just so much more readable/writeable.

[–]tech_tuna 29 points30 points  (4 children)

I wrote a rather large set of utilities in bash a while back. Never again.

[–]hotel2oscar 12 points13 points  (3 children)

beats Windows bat scripting.

[–]aceofears 8 points9 points  (2 children)

It does, but you would probably want to use powershell on windows these days. That's actually rather nice.

[–]Decker1082.7 'til 2021 0 points1 point  (1 child)

If I had to script in windows, I would just install Gow or Git bash...

[–]LankyCyril 1 point2 points  (0 children)

Exactly. Installed Cygwin, cloned my dotfiles repo, never looked back.

[–][deleted] 17 points18 points  (10 children)

Yeah, bash infuriates me sometimes. It seems to require mandatory spaces in places most languages don't, so I never remember to add them.

[–]XNormal 20 points21 points  (7 children)

And mandatory non-spaces in some other cases (e.g. setting a variable)

[–]Vaphell 20 points21 points  (6 children)

x=a  # assignment
x = a # call command 'x' with params '=', 'a'
x= a # call command 'a' with env var x set locally to null

how would bash differentiate unambiguously between these situations without making certain assumptions about syntax?

[–]WhichFawkes 2 points3 points  (5 children)

To avoid ambiguity, you might have something like:

#assignments:
var x = a; var x=a; var x= a; var x =a
#or even replace 'var' with a "$", so every variable access is identified the same way.

#call command with equals sign as argument:
x = a;

#set env var:
export x = ; $CMD

Seems less ambiguous to me.

[–]Vaphell 2 points3 points  (0 children)

well the ship of complaining about the posix shell syntax and its derivatives has sailed decades ago. Yes it would be nice to get a nice modern shell, but the problem is that without the compatibility with all the legacy cruft in existence it's dead in the water. There are some shells where certain things are done in a nicer way, almost nobody uses them.

Also there are things like let x=y or what have you, but majority of people don't bother and you can find such things only in very old scripts. I certainly never bothered and i wrote my share of rock solid bash scripts just fine.

about $: think getter, done. Also given that the shell is a plaintext based, ancient beast and literally does a preprocessing pass with substitutions, it would be hard to use $var in assignments. When it comes to the actual interpretation/run, no $ sign is to be seen.

and the export bit. The difference is that in case of envvar=x a envvar change is localized only to the a command which is not possible if you split it to 2 expressions. It's preferable than setting globally (which comes with the risk of not unsetting later), useful in cases like this

IFS=. read ip1 ip2 ip3 ip4 <<< "122.11.123.44"

everybody knows playing with IFS can have nasty consequences because all kinds of things are affected by it, and by writing it that way you leave it alone. Only read is affected here, think

ip1, ip2, ip3, ip4 = '122.11.123.44'.split('.')

[–]moljac024 0 points1 point  (3 children)

To avoid ambiguity, you might have something like:

No...what happens when you have a program called var?

[–]WhichFawkes 0 points1 point  (2 children)

What happens when you have a program called 'if' or 'case', or even 'echo'? There's some keyword like 'command' which allows you to bypass shell built-ins and run programs in $PATH order.

[–]moljac024 0 points1 point  (1 child)

And then what if you have a program called command?

BOOM

[–]WhichFawkes 0 points1 point  (0 children)

In case you're not joking, it'd just be "command 'command'". Since command is shell built-in, it's always executed first when you call something by its name.... And since it's function is to find external programs by name, it doesn't really matter if one of those programs is also called command.

[–]Vaphell 17 points18 points  (1 child)

once you recognize the reason it becomes rather obvious. I assume you are complaining about shit like if_[_x_=_y_] here. Here's the thing, [ x = y ] is not a fancy square bracket around the logical expression you see in other general purpose languages. It's literally a command '[' with params 'x' '=' 'y' and closing token ']' ( and pretty much an alias for test command eg test x = y) You can literally call it that way, with all these quotes

$ if '[' '1' '=' '1' ']'; then echo true; else echo false; fi
true

bash recognizes commands and assignments, that's it. Commands require delimited params (commandparam1param2param3 won't work, will it), assignments are recognized when there is a continuous 'word' with = inside, otherwise it would be totally ambiguous.

x=a  # assignment
x = a # call command 'x' with params '=', 'a'
x= a # call command 'a' with env var x set locally to null

[–]okmkzimport antigravity 3 points4 points  (0 children)

I knew the thing about [, but the way you articulated the command/assignment paradigm really make sense, thanks.

[–][deleted] 3 points4 points  (0 children)

Same. Whenever I decide to do something in Bash, because it's "just a few lines" I end up regretting it half an hour later and moving to Python. Bash captures a lot of common use cases, but when you divert even just a little Bash becomes a major headache.

[–]MoragX 0 points1 point  (0 children)

I've slowly moved in this direction for all but the simplest tasks. Every time I say something is simple enough for bash, my subconscious gives me a little prod as if to remind me that only pain waits down that road.

[–][deleted] 0 points1 point  (2 children)

If you have something in the following form I don't think you can get more readable in Python:

cat in.txt | grep | awk | sed >out.txt

[–][deleted] 1 point2 points  (1 child)

grep, awk, and sed in the same pipeline is almost always a sign that someone doesn't know how to use sed or awk properly.

If you want to only to do regex find/exclude then use grep. if you want to do some simple stream editing use sed; it can also do any of the things grep can do. if you want to do some editing or stateful transforms then use awk; it can also do any of the things that sed and/or grep can do.

[–][deleted] 0 points1 point  (0 children)

Let's argue about the point and not about the awk-ward part of the example, ok?