Setting environment variable with leading digit in bash - linux

I need to set an environment variable called "64bit" (i.e. with a leading digit) in bash. However, bash variable names disallow a variable with a leading digit. I know a way to set it when invoking bash:
env 64bit=1 /usr/bin/bash
However, I'm looking for a way to change it in the currently running shell i.e. not by starting a new shell. I also know that csh allows variables to start with a digit, but I need to use bash.
Is there any way to achieve this?

You can also bypass the bash interpreter and define the variable directly with the bash internal functions:
$ gdb --batch-silent -ex "attach $$" \
-ex 'set bind_variable("64bit", "1", 0)' \
-ex 'set *(int*)(find_variable("64bit")+sizeof(char*)*5) = 1' \
-ex 'set array_needs_making = 1'
$ env | grep 64
64bit=1

As people point out, Bash does not allow variables starting with digits. It does however pass on unrecognized environment string to external programs, which is why the variable shows up in env but not in set.
As a workaround, you can work with a valid name like _64bit and then automatically inject your invalid variable name into commands you run:
#!/bin/bash
# Setup for injection hack
original=$PATH
PATH="/"
command_not_found_handle() {
PATH="$original" env "64bit=$_64bit" "$#"
}
# Your script and logic
_64bit="some dynamic value"
# This verifies that '64bit' is automatically set
env | grep ^64bit
Note that this particular method only works if you invoke through $PATH, not if you use relative or absolute path names.
If you do invoke by pathname, consider modifying PATH and invoking by name instead.

Related

Pass in bash terminal variables to a bash script

If I am in a Linux terminal and I start setting variables such as export AGE=45.
Then I have a script to read user data from terminal variables and process it, is this possible to do?
IE:
user#linux$ export AGE=45
user#linux$ ./age.sh
#script asks for input
read -p "what is your age?" scriptAGE
#user inputs variable set in terminal
$AGE
#echo output
echo "your age is: " $scriptAGE"
#should say your age is: 45
There is no such thing as a terminal variable. read just assigns a string to your variable scriptAGE.
If this string contains some $NAME you want to expand, you could apply eval to it, but this is of course extremely dangerous because of possible code injection.
A safer way to do this is using envsubst, but this requires that the variables to be substituted must be environment variables. In your case, AGE is in the environment, so this condition is met.
In your case, you would have to do therefore a
envsubst <<<"$scriptAGE"
which would print on stdout the content of scriptAGE with all environment variables in it substituted.
Variables are not expanded in input, only in the script itself.
You could use eval to force it to process the variable value as shell syntax.
eval "echo 'your age is:' $scriptAGE"
But this will also process other shell syntax. If they enter $AGE; rm * it will say their age is 45 and then delete all their files.
you could just do
age=$1
echo "Your age is $1"
where $1, $2, $3, .., $N are the passed arguments by order
And then run your script
bash script sh Noureldin
For more Info read this:
passing names args

Using Linux environmental variables as a path in Perl script

I am trying to use an environmental variable to point to a file, run it through a subroutine and associate it with a variable. I managed it with Windows but I cannot get the syntax working for Linux..
This is what I have:
my $config = read_config("$ENV{APP_HOME}/config/APP-linux.cfg");
my script dies when reaching this line with the error:
Use of uninitialized value $ENV{"APP_HOME"} in concatenation (.) or string at ./XXXXX.pl
APP_HOME is defined as an environment variable (confirmed using set). What am I doing wrong?
In bash, = simply creates a shell variable. These are not automatically exported to the environment. You need to do that explicitly.
Set a shell variable:
$ AA=hello
Set and export another one (in a single statement):
$ export BB=there
Start a new process:
$ bash
Voila! Only the exported variable is inherited by the new process:
$ echo "[$AA] [$BB]"
[] [there]
Note that set does not set a variable. set AA=hello does not do what the Windows shell does.
Okay, the solution was of my own stupidity. I set the variable in .bashrc using:
APP_HOME=$HOME/APP/DATA/STORAGE; export FINE_DIR
The RAPID_DIR had no right to be there. Was a remainder of a copy/paste and poor oversight... Changes FINE_DIR to APP_HOME and all is good.
Thankyou for all the guidance!

Read environment variable in make file

I have a environment variable set with name $MY_ENV_VARIABLE.
How do I use this variable inside my makefile to (for example) include some source files?
LOCAL_SRC_FILES = $(MY_ENV_VARIABLE)/libDEMO.so
Something like above doesn't seem to work.
Note: in my case this is needed for building with the Android NDK but I guess this applies to make in general.
Just to add some information...
The syntax to access the environment variable in make is like other variables in make...
#export the variable. e.g. in the terminal,
export MY_ENV_VARIABLE="hello world"
...
#in the makefile (replace before call)
echo $(MY_ENV_VARIABLE)
This performs the substitution before executing the commmand. If you instead, want the substitution to happen during the command execution, you need to escape the $ (For example, echo $MY_ENV_VARIABLE is incorrect and will attempt to substitute the variable M in make, and append it to Y_ENV_VARIABLE)...
#in the makefile (replace during call)
echo $$MY_ENV_VARIABLE
Make sure you exported the variable from your shell. Running:
echo $MY_ENV_VARIABLE
shows you whether it's set in your shell. But to know whether you've exported it so that subshells and other sub-commands (like make) can see it try running:
env | grep MY_ENV_VARIABLE
If it's not there, be sure to run export MY_ENV_VARIABLE before running make.
That's all you need to do: make automatically imports all environment variables as make variables when it starts up.
I just had a similar issue (under Cygwin):
Running echo $OSTYPE on the shell prints the value, but
running env | grep OSTYPE doesn't give any output.
As I can't guarantee that this variable is exported on all machines I want to run that makefile on, I used the following to get the variable from within the makefile:
OSTYPE = $(shell echo $$OSTYPE)
Which of course can also be used within a condition like the following:
ifeq ($(shell echo $$OSTYPE),cygwin)
# ...do something...
else
# ...do something else...
endif
EDIT:
Some things I found after experimenting with the info from jozxyqk's answer, all from within the makefile:
If I run #echo $$OSTYPE or #echo "$$OSTYPE" in a recipe, the variable is successfully expanded into cygwin.
However, using that in a condition like ifeq ($$OSTYPE,cygwin) or ifeq ("$$OSTYPE","cygwin") doesn't expand it.
Thus it is logical that first setting a variable like TEST = "$$OSTYPE" will lead to echo $(TEST) printing cygwin (the expansion is done by the echo call) but that doesn't work in a condition - ifeq ($(TEST),cygwin) is false.

Shell script for setting environment variable

I am writing a shell script to set the environment variables whose values are available in a file. Below is the shell script I wrote,
VARIABLE_FILE=env-var.dat
if [ -f ${VARIABLE_FILE} ] ; then
. ${VARIABLE_FILE}
if [ ! -z "${TEST_VAR1}" ] ; then
export TEST_VAR1="${TEST_VAR1}"
fi
if [ ! -z "${TEST_VAR2}" ] ; then
export TEST_VAR2="${TEST_VAR2}"
fi
fi
The above code works only in bash shell, since I have used export command to set the environment variable and it fails if I used it with any other shell. Is there is any command to set the environment variable which works in any shell ?
"Fancier" shells like bash and zsh permit you to set a variable and export it as an environment variable at the same time like so:
export FOO=bar
With a standard POSIX bourne shell, the equivalent is achieved by doing it in two commands:
FOO=bar
export FOO
Note that once you've exported a variable, you can reset it to a different value later in the script and it's still exported (you don't need to export it again). Also, you can export several variables at a time:
FOO=bar
BAZ=quux
export FOO BAZ
You mentioned tcsh in your comment, but csh and derivatives are completely different from bourne-based shells (and not recommended for use!). You can rarely make a shell script compatible with both sh and csh at the same time. For csh, look into setenv
If you really want this to happen, it can be done, but it's tricky. One way to do it is to use awk to output the correct syntax and evaluate the text coming back from awk. To share a single environment variable value file between major sh and csh flavors, the following command in a file will import a variable value file to the environment: (yes, yes, it's one huge line, due to the inflexible way that some shells treat the backticks. If you didn't mind having a .awk file too, you could use awk -f...)
eval `awk '{ var = $1; $1=""; val=substr($0,2); if ( ENVIRON["SHELL"] ~ /csh$/) { print "setenv", var, " \"" val "\";" } else { print var "=\"" val "\"" ; print "export", var }}' $HOME/env_value_file`
The variable value file is in this format:
FOO value for foo
BAR foo bar
BAZ $BAR plus values $FOO
Design notes for educational purposes:
In awk, there's no easy way of accessing fields 2-NF, so if there
could be spaces in our variable values we need to modify $1 to get
$0 to be close to get the value we want.
To get this to work, since a SHELL variable is always set, but not as an
environment variable and not with a consistent capitalization, you have to wet
a SHELL environment variable from the shell's value as below.
as an environment variable before you use the script.
Also, if you want the new environment values to be present after the import
environment script you need to source the environment script.
If a shell doesn't do eval well, you'll have to tweak the script.
For bourne shell flavors (bash, sh, ksh, zsh):
export SHELL
. import_environment
For csh flavors: (shell variable tends to be lower case in csh shells)
setenv SHELL "$shell"
source import_environment

check if environment variable is already set [duplicate]

This question already has answers here:
What's a concise way to check that environment variables are set in a Unix shell script?
(14 answers)
Closed 9 years ago.
I am writing a shell script, where I have to check if environment variable is set, if not set then I have to set it. Is there any way to check in shell script, whether an environment variable is already set or not ?
The standard solution to conditionally assign a variable (whether in the environment or not) is:
: ${VAR=foo}
That will set VAR to the value "foo" only if it is unset.
To set VAR to "foo" if VAR is unset or the empty string, use:
: ${VAR:=foo}
To put VAR in the environment, follow up with:
export VAR
You can also do export VAR=${VAR-foo} or export VAR=${VAR:=foo}, but some older shells do not support the syntax of assignment and export in the same line. Also, DRY; using the name on both sides of the = operator is unnecessary repetition. (A second line exporting the variable violates the same principal, but feels better.)
Note that it is very difficult in general to determine if a variable is in the environment. Parsing the output of env will not work. Consider:
export foo='
VAR=var-value'
env | grep VAR
Nor does it work to spawn a subshell and test:
sh -c 'echo $VAR'
That would indicate the VAR is set in the subshell, which would be an indicator that VAR is in the environment of the current process, but it may simply be that VAR is set in the initialization of the subshell. Functionally, however, the result is the same as if VAR is in the environment. Fortunately, you do not usually care if VAR is in the environment or not. If you need it there, put it there. If you need it out, take it out.
[ -z "$VARIABLE" ] && VARIABLE="abc"
if env | grep -q ^VARIABLE=
then
echo env variable is already exported
else
echo env variable was not exported, but now it is
export VARIABLE
fi
I want to stress that [ -z $VARIABLE ] is not enough, because you can have VARIABLE but it was not exported. That means that it is not an environment variable at all.
What you want to do is native in bash, it is called parameter substitution:
VARIABLE="${VARIABLE:=abc}"
If VARIABLE is not set, right hand side will be equal to abc. Note that the internal operator := may be replaced with :- which tests if VARIABLE is not set or empty.
if [ -z "$VARIABLE" ]; then
VARIABLE=...
fi
This checks if the length of $VARIABLE is zero.

Resources