MacOS export of env var is being escaped or misinterpreted on shell - macos

Mac OS here. On the terminal, I create the following .env file:
export FIZZ=foo
export BUZZ="$2a$10$Hk1PB6Eyf5Pu71JLfH6fCexjzOIwkctk.pQJ4oYWP.m4qdRKRQlyO"
Then I run source .env && echo $FIZZ and I see:
foo
So far, so good. But now I run echo $BUZZ and the output is:
a0.pQJ4oYWP.m4qdRKRQlyO
I explicitly put the value for BUZZ in double quotes ("$2a$10$Hk1PB6Eyf5Pu71JLfH6fCexjzOIwkctk.pQJ4oYWP.m4qdRKRQlyO"), so why is it outputting as "a0.pQJ4oYWP.m4qdRKRQlyO"?

I was able to reproduce what you saw. I'm pretty sure you're having issues with the environment variable substitution that bash does. (triggered by the "$" character.) I know of two ways to "fix" it.
One is to escape the "$" characters with a preceding backslash.
export BUZZ=\$2a\$10\$Hk1PB6Eyf5Pu71JLfH6fCexjzOIwkctk.pQJ4oYWP.m4qdRKRQlyO
Another is to change the way you quote the string. Use single quotes instead of double quotes...
export BUZZ='$2a$10$Hk1PB6Eyf5Pu71JLfH6fCexjzOIwkctk.pQJ4oYWP.m4qdRKRQlyO'.
The double quotes allow environment variable substitution to continue, the single quotes prevent that from occurring.

Related

Why are quotes preserved when using bash $() syntax, but not if executed manually?

I have the following bash script:
$ echo $(dotnet run --project Updater)
UPDATE_NEEDED='0' MD5_SUM="7e3ad68397421276a205ac5810063e0a"
$ export UPDATE_NEEDED='0' MD5_SUM="7e3ad68397421276a205ac5810063e0a"
$ echo $UPDATE_NEEDED
0
$ export $(dotnet run --project Updater)
$ echo $UPDATE_NEEDED
'0'
Why is it $UPDATE_NEEDED is 0 on the 3rd command, but '0' on the 5th command?
What would I need to do to get it to simply set 0? Using UPDATE_NEEDED=0 instead is not an option, as some of the other variables may contain a space (And I'd like to optimistically quote them to have it properly parse spaces).
Also, this is a bit of a XY problem. If anyone knows an easier way to export multiple variables from an executable that can be used later on in the bash script, that could also be useful.
To expand on the answer by Glenn:
When you write something like export UPDATE_NEEDED='0' in Bash code, this is 100% identical to export UPDATE_NEEDED=0. The quotes are used by Bash to parse the command expression, but they are then discarded immediately. Their only purpose is to prevent word splitting and to avoid having to escape special characters. In the same vein, the code fragment 'foo bar' is exactly identical to foo\ bar as far as Bash is concerned: both lead to space being treated as literal rather than as a word splitter.
Conversely, parameter expansion and command substitution follows different rules, and preserves literal quotes.
When you use eval, the command line arguments passed to eval are treated as if they were Bash code, and thus follow the same rules of expansion as regular Bash code, which leads to the same result as (1).
Apparently that Updater project is doing the equivalent of
echo "UPDATE_NEEDED=\'0\' MD5_SUM=\"7e3ad68397421276a205ac5810063e0a\""
It's explicitly outputting the quotes.
When you do export UPDATE_NEEDED='0' MD5_SUM="7e3ad68397421276a205ac5810063e0a",
bash will eventually remove the quotes before actually setting the variables.
I agree with #pynexj, eval is warranted here, although additional quoting is recommended:
eval export "$(dotnet ...)"

Exporting env vars with whitespace outputted by a script (bash)

I have a script that outputs a list of env vars like:
THING=one
ANOTHER_THING=two
A_PATH="path/to a/directory"
When I try to export these env vars as export `./script`, the A_PATH env var exports as path/to.
If I export the list as plain text like:
export THING=one ANOTHER_THING=two A_PATH="path/to a/directory", it works just fine.
I'm stumped as to why bash treats the white space in the A_PATH differently in these two cases. I've tried various attempts at escaping the whitespace and I've even tried exporting line by line, but in every case it sees the whitespace as a delimiter rather than as a part of the path string.
why bash treats the white space in the A_PATH differently in these two cases
The result of command substitution `...` undergoes word splitting. Do not use ` backticks - use $(....) instead. Check your scripts with shellcheck.net .
Spaces inside string around double quotes are literally preserved. See quoting.
If the file has proper correct shell syntax, and it's meant to be sourced and support shell-ish execution, see https://unix.stackexchange.com/questions/614568/is-is-possible-to-export-all-variables-obtained-from-sourcing-a-file . If the file contains = separated variable name and optionally quoted string with custom syntax, write a parser for the file for that syntax - see ex. Parsing variables from config file in Bash for a stub to get started.
Without the actual code, it is difficult to understand what is going on. But one workaround that might solve your problem is to output the export command and evaluate it.
Example (script.sh):
#!/bin/bash
echo "export THING=one"
echo "export ANOTHER_THING=two"
echo "export A_PATH='path/to a/directory'"
eval $(./script.sh)

How do I avoid calling part of my string as a command?

I run with the file with command line arguments:
samplebash.bsh fakeusername fakepassword&123
.bsh file:
echo "Beginning script..."
argUsername='$1'
argPassword='$2'
protractor indv.js --params.login.username=$argUsername --params.login.password=$argPassword
Output:
Beginning script...
123: command not found
The Issue: For some reason, it interprets what follows the & symbol from the password as a command, how do I avoid this?
The problem isn't happening in your script, it's happening in your original command line. & is a command terminator, which specifies that the command before it should be executed in the background. So your command was equivalent to:
samplebash.bsh fakeusername fakepassword &
123
You need to quote the argument to prevent special characters from being interpreted by the shell.
samplebash.bsh fakeusername 'fakepassword&123'
Also, you shouldn't put single quotes around a variable like you do in your assignments, that prevents the variable from being expanded. So it should be:
argUsername=$1
argPassword=$2
And you should put double quotes around the variables when you use them in the command, to prevent wildcards and whitespace from being interpreted.
protractor indv.js --params.login.username="$argUsername" --params.login.password="$argPassword"
As a general rule, you should always put double quotes around variables unless you know they're not needed.

Expansion of bash variable in multiple quotes?

I am trying to perform a cURL command within a bash script to POST to a URI. The command requires that one of the arguments be surrounded by double and single quotes i.e. '"jsimmons"' In my script however this argument is a variable so the command keeps failing which I believe is because the variable is doing some weird expansion and the command is losing the quotes necessary.
For my current attempt, which doesn't work, the argument looks like, '""$watcher""' as I am trying to expand the variable and place that string within the double and single quotes.
How can I expand my variable properly to fulfill the requirements of the command?
If you have double quotes around your whole command, you can insert single quotes without any trouble but need to escape double quotes.
For example:
$ watcher=jsimmons
$ echo "'\"$watcher\"'"
'"jsimmons"'
You can escape the surrounding 's and "s with \
\'\"$watcher\"\'

Bash prompt not recognizing variables

I'm customizing my bash prompt (I use iTerm on OS X Lion), and have tried something like:
PS1='\n[\u]-> '
Just for simplicity, but after reloading my ~/.bash_profile, my prompt now says:
\n[\u]->
and not what I'm expecting to (a new line, followed by my username).
Any ideas?
How is the shell being invoked? If it's as sh, or possibly other ways, it won't be interpreted. Try echo $0
Notice the single quotes in your prompt? Bash syntax treats single and double quotes differently. Use double quotes to allow the shell to expand the special chars.
Also, do you have promptvars set?
Try replacing the single quotes with double quotes, i.e. PS1="\n[\u]-> ".

Resources