How to export dot separated environment variables - macos

Execution of
user#EWD-MacBook-Pro:~$ export property.name=property.value
Gives me
-bash: export: `property.name=property.value': not a valid identifier
Is it possible to have system properties with dot inside? If so how do that?

As others have said, bash doesn't allow it so you'll have to use your favourite scripting language to do it. For example, in Perl:
perl -e '$ENV{"property.name"} = "property.value"; system "bash"'
This will fire up a subshell bash with the property.name environment variable set, but you still can't access that environment variable from bash (although your program will be able to see it).
Edit: #MarkEdgar commented that the env command will work too:
env 'property.name=property.value' bash # start a subshell, or
env 'property.name=property.value' command arg1 arg2 ... # Run your command
As usual, you only require quotes if you need to protect special characters from the shell or want to include spaces in the property name or value.

I spent better part of this afternoon trying to figure out how to access some property set by Jenkins (to pass a job parameters jenkins uses property format with a dot) - this was a good hint from Adrian and yes it works for reading properties in the script too. I was at a loss as to what to do but then I tried:
var=`perl -e 'print $ENV{"property.name"};print "\n";'`
This worked quite well actually. But of course that works in a shell that was started with the property set in the environment already i.e. in Adrian's example this could work in a script started from bash instance invoked in perl example he provided. It would not if this perl sniplet was put in the same shell only directly after his perl example.
At least I learnt something this afternoon so not all this time is a waste.

If you export those properties to run an application, some programs can support setting system property as an option, and allow . in the property name.
In Java world, most of tools support setting system property by -D option, e.g. you can set system property with dot like this -Dproperty.name=property.value.

Bash only permits '_' and alpha numeric characters in variable names. The '.' isn't permitted.
http://tldp.org/LDP/abs/html/gotchas.html

Related

source a file containing environment variables including "dash" character in bash?

I'm using bash and have a file called x.config that contains the following:
MY_VAR=Something1
ANOTHER=Something2
To load these as environment variables I just use source:
$ source x.config
But this doesn't work if MY_VAR is called MY-VAR:
MY-VAR=Something1
ANOTHER=Something2
If I do the same thing I get:
x.config:1: command not found: MY-VAR=Something1
I've tried escaping - and a lot of other things but I'm stuck. Does anyone know a workaround for this?
A pure bash workaround that might work for you is to re-run the script using env to set the environment. Add this to the beginning of your script.
if [[ ! -v myscript_env_set ]]; then
export myscript_env_set=1
readarray -t newenv < x.config
exec env "${newenv[#]}" "$0" "$#"
fi
# rest of the script here
This assumes that x.config doesn't contain anything except variable assignments. If myscript_env_set is not in the current environment, put it there so that the next invocation skips this block. Then read the assignments into an array to pass to env. Using exec replaces the current process with another invocation of the script, but with the desired variables in the environment.
A dash (-) in an environment variable is not portable, and as you noticed, will cause a lot of problems. You can't set these from bash. Fix the application you want to invoke.
That being said, if you can't change the target app, you can do this from python:
#!/usr/bin/python
import os
with open('x.config') as f:
for line in f:
name, value = line.strip().split('=')
os.environ[name] = value
os.system('/path/to/your/app')
This is a very simplistic config reader, and for a more complex syntax you might want to use ConfigParser.

Run simple programme using unix shell

I'm new to unix and its developing. In my new.sh script I wrote
$USERNAME=user
$PASSWORD=sekrit
echo $USERNAME
and ran new.sh using bash new.sh
But I get the following errors
new.sh: line 1: =user: command not found
new.sh: line 2: =sekrit: command not found
How do I run that command and print the username variable in terminal?
USERNAME is the name of the variable. $USERNAME is the replacement (aka contents, aka value). Since USERNAME is empty, you effectively try to run a command named =user, which is what the error message tells you.
Remove the $ from $USERNAME=... and it will work.
As Jens notes in his answer, the problem is that an assignment to a variable is not prefixed with a $, so:
USERNAME=user
PASSWORD=sekrit
is the way to write what you wanted. You got an error because USERNAME was not set, so after expansion, the shell looked at the command as:
=user
=sekrit
and it could not find such commands on the system (not very surprisingly). However, be aware that if you have previously written:
USERNAME=archipelago
PASSWORD=anchovy
then the lines:
$USERNAME=user
$PASSWORD=sekrit
would have been equivalent to writing:
archipelago=user
anchovy=sekrit
You could see that by running set with no arguments; it would show you the values of all the variables set in the shell. You could search for words such as USERNAME and archipelago to see what happened.
Now you've learned that, forget it. The number of times you'll need to use it is very limited (but it is handy on those rare — very rare — occasions when you need it).
For all practical purposes, don't write a $ on the left-hand side of a variable assignment in shell.

Save Global variables BASH

I am new at bash and trying to solve some issues for a code I'm trying to make.
I am at the terminal under my user name and connect to bash
USER$
USER$ bash
bash$
now in the bash I am saving some variables f.e:
i=2
k=2
let p=$k*$i
now I want to use those variables outside the bash function
bash$exit
USER$
but now the variables are not there
I try using export, but it did not really work, could use ur help, tnx
Not possible. You cannot set environment variables in a parent process like this.
Unlike a DOS batch file, a Unix shell script cannot directly affect the environment of its calling shell.
You could consider using the . (dot) or source command to read and execute the script in the context of the calling shell. This means that changes made in the script do affect the environment (in general; you can still run into issues with sub-shells).
The other alternative is to have the script that sets the variables write the values in name=value format into a file which the calling script then reads (with . or source again).
The conventional solution is to add the settings to your .profile or . bashrc -- which you should use depends on your specific needs and your local Bash configuration; my first recommendation would be .profile, but then you have to avoid any bashisms because this file is shared with sh (so, no let, for example).
For more specific needs, put the commands in a file, and source it when you need it. You might also want to create a simple script to update the file with your current values.
# source this file to update $HOME/stuff
cat<<HERE>$HOME/stuff
i='$i'
k='$k'
p='$p'
export i k p
HERE
The syntax here is quite simple, but assumes you don't have values which can contain single quotes or otherwise free-form content. How to safely store arbitrary values which you don't have complete control over is a much more complex discussion; I am providing a simple solution for the basic use case where you merely need to save a few simple scalar values, like numbers.
To keep your variables when you connect to a remote system, look at the documentation for the tool you are using to connect. For example, ssh has configuration options for importing environment variables from the local system when starting a remote session.

Variables that work everywhere

How can I set variables that work everywhere? My .bashrc has:
Questions='/Users/User/Stackoverflow/Questions'
Address='My address'
My file has:
$Questions
$Addres
The command "$ cat my_file" in Shell prints "$Questions" and "$Address", instead of "/Users/User/Stackoverflow/Questions" and "My address". Other places where I would like have the variables are Email and Browser. But I cannot get them working.
How can I have my variables to work in every program?
cat doesn't interpret variables. It simply prints out the contents of a file, byte-for-byte.
If you want to be able to print out the values of the variables with my_file, I would suggest changing it to read
echo "$Questions"
echo "$Address"
Then you can "source" it (kind of like running it in the current shell environment) with
$ source my_file
or
$ . my_file
You might also have to use export in .bashrc, like so:
export Questions='/Users/User/Stackoverflow/Questions'
export Address='My address'
How can I have my variables to work in every program?
You can't. Bash and cat are two separate programs. You set a bash variable, it doesn't mean that cat will behave like bash to interpret it. $VARNAME is a shell syntax, cat is a different program, that share almost nothing with the shell.
You can export the shell variable as an environment variable, but cat is not programmed to replace any text templates, it goes way beyond its purpose.
Instead, you may use sed to perform text template substitutions:
sed -e "s|#QUESTIONS#|$Questions|g; s|#ADDRESS#|$Address|g" file.txt
This will replace all instances of #QUESTIONS# and #ANSWERS# in the file with the contents of $Questions and $Address shell variables. Note that these shell variables must not contain any pipe ("|") symbols, since the suggestion uses them as delimiters.
You can get the "cat" thing to work using some nasty hackery:
eval "$(printf 'cat << END\n%s\nEND' "$(< foo)")"
Where "foo" is the file that contains your text you want the bash parameters expanded from. This solution basically just converts the text into a here document, which does expand bash parameters.
cat <<END
[your text]
END
Limitations:
You can't have a line with just "END" in the text file or the solution will break. It'll think the line with "END" in the text file ends the here document instead of the END in the printf command, and the ouput will end early.
TBH:
This is something you just shouldn't want to do. If you want to make template files, go find a templating system that's built for this. You shouldn't be raping bash into doing something that it isn't built to do. It's a scripting language, not a templating system. It's built to parse scripts with a well defined syntax, not arbitrary text files.
You can't. In order to do that, you'd need the cooperation of every email client writer, every browser writer, every utility writer.
Type env see if the variables exist.
If so, try calling them with ${VAR_NAME}.
After re-iterating I now see your problem. You just can't have a text file, cat out it's content and expect the environments variables to be parsed. You just can't.
If it was a bash script file, and you were to run it, you could echo out the variables and they would be parsed like you want.
From your comment on Paul Tomblin's answer:
Are you sure? I have heard that you can have all kind of things like RSS-reader in Emacs. Perhaps, there is a better cooperation. I am a VIM-user, so I don't know. If someone knows whether Emacs has great cooperation between programs, please do not hesitate to share your knowledge. – UnixBasics (3 mins ago)
Do you want (or would you be satisfied with) an editor that can expand your environment variables?
That is a different (i.e. simpler, and possible) problem.
On purely theoretical level, I suppose a hacked filesystem could do what you want, but it would certainly break all kinds of binary storage. So we add a filesystem flag for text (expandable) and non-text file types. And we'd need a way for the filesystem to know what set of variable to expand, and ad nauseum...
Just add to your ~/.profile or to ~/.bashrc:
export Questions='/Users/User/Stackoverflow/Questions'
export Address='My address'

Windows Command Line: Non Evaluation of Environment Variable

I would like to provide the raw text referring to an environment variable to a command instead of evaluating the environment variable.
I need this to configure BizTalk from the command line, for example:
BTSTask.exe AddResource -ApplicationName:App1
-Type:System.BizTalk:BizTalkAssembly -Overwrite
-Source:..\Schemas\bin\development\App1.Schemas.dll
-Destination:%BTAD_InstallDir%\App1.Schemas.dll
This command adds a resource to a BizTalk application. I want the destination to be %BTAD_InstallDir%\App1.Schemas.dll, however at present it is evaluating the environment variable (to nothing) and using \App1.Schemas.dll.
Is it possible to escape or disable the evaluation of this environment variable while parsing\executing this command?
I have tried escaping the first and both percentage characters with a carrot (^), however this did not stop the evaluation.
[EDIT] When I execute this at the command prompt it doesn't replace the environment variable, however it does when I run it as a script, any thoughts as to why this is different?
Try echo ^%path^% in a command prompt it prints...
path
instead of expanding the environment variable so I guess the following should work for you as suggested by Mikeage
BTSTask.exe AddResource -ApplicationName:App1 -Type:System.BizTalk:BizTalkAssembly -Overwrite -Source:..\Schemas\bin\development\App1.Schemas.dll -Destination:^%BTAD_InstallDir^%\App1.Schemas.dll
Did you try:
%%BTAD_InstallDir%%
in your script ?
That should prevent the script to interpret the variable, and it would pass %BTAD_InstallDir% to the program.
Try ^% instead of %.
Tried:
C:\PrgCmdLine\Unix\echo.exe "%"JAVA_HOME"%"
Got:
%JAVA_HOME%
[EDIT] Indeed, C:\PrgCmdLine\Unix\echo.exe ^%JAVA_HOME^% works too, and is simpler...
[EDIT 2] For the record: I used UnxUtils' echo to have the behavior of a plain program. Built in echo has a slightly different behavior, at least for quoted % signs.
Not sure if it's the same as my case, but i was troubling to use a batch file to create a script which has %temp% variable inside.
The workaround i found:
set test=%temp;
echo {command} %test%%>>path_to_my_batch_file;
Hope this helps someone:)

Resources