Exporting dependant variable failed in shell script - bash

I have three shell script files, one global variable named "VER" and its value is "2017.4"
1. variable.sh
2. function.sh
3. main.sh
variable.sh
var1=/home
var2=/home/${VER}_version
function.sh
Contain a function named export_function which takes one variable as argument, perform grep operation to find that variable from variable.sh file and export the grep output
export_function () {
var=`grep "$1=" variable.sh | sed -e "s/"$1="//g"`
export $1=$var
}
main.sh
source function.sh
export_function var2
echo "$var2"
When I run the main.sh, get output: /home/${VER}_version instead of /home/2017.4_version
Note: echo $VER in main.sh and function.sh shows value 2017.4
Constrains:
variable.sh is a read-only file
source variable.sh is not allowed

I've rewritten your scripts like that, and it works:
[sahaquiel#sahaquiel-PC ~]$ cat variable.sh
#!/bin/bash
var1=/home
var2="/home/${VAR22}_version"
[sahaquiel#sahaquiel-PC ~]$ cat function.sh
#!/bin/bash
export_function () {
source variable.sh
var=$(echo "var2=${var2}" | grep "$1=" | sed -e "s/"$1="//g")
export $1=$var
}
[sahaquiel#sahaquiel-PC ~]$ cat main.sh
#!/bin/bash
source function.sh
export_function var2
echo "$var2"
[sahaquiel#sahaquiel-PC ~]$ bash main.sh
/home/2017.4_version
[sahaquiel#sahaquiel-PC ~]$ echo $VAR22
2017.4

Related

Bash function argument parsing

I want to have a function I can call from the command line that takes the following:
$ command_name /some/path/file.java
and turns into the following call:
command /some/path:file
So basically the part I'm having trouble with is substituting a : for the last / and stripping the file extension.
It's not 100% clear what you question is. Do you want a bash function or a bash script? Splitting paths and files is easily done with the commands basename and dirname.
e.g.:
$ dirname /path/to/file.txt
/path/to
$ basename /path/to/file.txt
file.txt
But if you must do it with a regex, sed works well:
$ echo /path/to/file.txt | sed "s/.*\///"
file.txt
$ echo /path/to/file.txt | sed -r "s/(.+)\/.+/\1/"
/path/to
First a script:
#! /usr/bin/env bash
COMMAND="/bin/echo"
JAVA="$1"
path=`dirname "$JAVA"`
file=`basename "$JAVA"`
exec "$COMMAND" "$path:$file"
And now a function:
fnA()
{
COMMAND="$1"
JAVA="$2"
path=`dirname "$JAVA"`
file=`basename "$JAVA"`
exec "$COMMAND" "$path:$file"
}
Assuming that the original path string,
/some/path/file.java
is passed to your script as $1, you get the modified string as
path_string_with_colon=$(dirname $1):$(basename $1 .java)

sed command find and replace in file and overwrite file , how to initialize file has current file/script

I wanted to increment the current decimal variable,
so I made the following code
#! /bin/bash
k=1.3
file=/home/script.sh
next_k=$(echo "$k + 0.1" | bc -l)
sed -i "s/$k/$next_k/g" "$file"
echo $k
As you can see here I have to specify the file in line 3 , is there a workaround to just tell it to edit and replace in the current file. Instead of me pointing it to the file. Thank you.
I think you're asking how to reference the own script name, which $0 holds, e.g.
#! /bin/bash
k=1.3
next_k=$(echo "$k + 0.1" | bc -l)
sed -i "s/$k/$next_k/g" "$0"
echo $k
You can read more on Positional Parameters here, specifically this bit:
($0) Expands to the name of the shell or shell script. This is set at shell initialization. If Bash is invoked with a file of commands (see Shell Scripts), $0 is set to the name of that file. If Bash is started with the -c option (see Invoking Bash), then $0 is set to the first argument after the string to be executed, if one is present. Otherwise, it is set to the filename used to invoke Bash, as given by argument zero.
e.g.
$ cat test.sh
#! /bin/bash
k=1.3
next_k=$(echo "$k + 0.1" | bc -l)
sed -i "s/$k/$next_k/g" $0
echo $k
$ ./test.sh; ./test.sh ; ./test.sh
1.3
1.4
1.5
$ cat test.sh
#! /bin/bash
k=1.6
next_k=$(echo "$k + 0.1" | bc -l)
sed -i "s/$k/$next_k/g" $0
echo $k

How can bash read from piped input or else from the command line argument

I would like to read some data either from pipe or from the command line arguments (say $1), whichever is provided (priority has pipe).
This fragment tells me if the pipe was open or not but I don't know what to put inside in order not to block the script (test.sh) (using read or cat)
if [ -t 0 ]
then
echo nopipe
DATA=$1
else
echo pipe
# what here?
# read from pipe into $DATA
fi
echo $DATA
Executing the test.sh script above I should get the following output:
$ echo 1234 | test.sh
1234
$ test.sh 123
123
$ echo 1234 | test.sh 123
1234
You can read all of stdin into a variable with:
data=$(cat)
Note that what you're describing is non-canonical behavior. Good Unix citizens will:
Read from a filename if supplied as an argument (regardless of whether stdin is a tty)
Read from stdin if no file is supplied
This is what you see in sed, grep, cat, awk, wc and nl to name only a few.
Anyways, here's your example with the requested feature demonstrated:
$ cat script
#!/bin/bash
if [ -t 0 ]
then
echo nopipe
data=$1
else
echo pipe
data=$(cat)
fi
echo "$data"
$ ./script 1234
nopipe
1234
$ echo 1234 | ./script
pipe
1234

Creating flag for print the output of shell script

I am creating a shell script. Now, I want to create a flag to print the output of script on the screen if flag is ON otherwise script will not print the output if flag is OFF
Thanks
This might work for you:
#!/bin/bash
# assuming your first argument is the printing flag
[[ "${1}" = "ON" ]] && OUTPUT="/dev/stdout" || OUTPUT="/dev/null"
# from now on:
echo "Something" > $OUTPUT
# will work as expected...
test.sh code below:
#!/bin/sh
while IFS= read -r line
do
cat "$line"
done < $1
Test it:
$ ls
myflags testfile0 testfile1 testfile2 test.py test.sh
$ cat myflags
testfile0
testfile1
test.py
$ cat testfile0
some test
$ sh test.sh myflags
some test
#!/usr/bin/python
import sys
if sys.version_info[0] == 2:
sys.stdout.write("ls -l")
$

reading variables from input file bash

I have an input file that looks like:
VAR1=1
VAR2=2
VAR3=3
VAR4=.T.
I'd like to read in these variables and define them as such. I've tried
while read line
do
exec $line
done < "Master.inp"
i've tried just
$line
instead, but that didn't work either. Is there a way to run the string as if I had just typed out the string in the bash file?
You can do it just sourcing the code:
. file
this will let you use the vars $VAR1, $VAR2, ...
Test
$ cat a
VAR1=1
VAR2=2
VAR3=3
VAR4=.T.
$ cat b
. a
echo $VAR1
$ ./b
1

Resources