Variable $1 as variable - bash

How can I set $1 variable as another variable? I want to run something like:
$ ./script london
Some output with John in text
And the script should be like:
#!/bin/bash
london="John"
ukraina="Yury"
romania="Ion"
cat /path/to/file | grep $1

I don't recommend blindly looking up variable names. A user could pass in any variable, not just one of the three you expect.
Instead, use an associative array.
declare -A names=([london]=John [ukraina]=Yury [romania]=Ion)
grep "${names[$1]}" /path/to/file
Or if your version of bash doesn't support associative arrays, use a case lookup.
case $1 in
london) name=John;;
ukraina) name=Yury;;
romania) name=Ion;;
esac
grep "$name" /path/to/file

#!/bin/bash
london="Jhon"
ukraina="Yury"
romania="Ion"
cat /path/to/file | grep ${!1}

If you want to declare $1 as variable use this:
VARIABLE="$1"
For example:
#!/bin/bash
VARIABLE="$1"
echo $VARIABLE

Related

How to parse multiple line output as separate variables

I'm relatively new to bash scripting and I would like someone to explain this properly, thank you. Here is my code:
#! /bin/bash
echo "first arg: $1"
echo "first arg: $2"
var="$( grep -rnw $1 -e $2 | cut -d ":" -f1 )"
var2=$( grep -rnw $1 -e $2 | cut -d ":" -f1 | awk '{print substr($0,length,1)}')
echo "$var"
echo "$var2"
The problem I have is with the output, the script I'm trying to write is a c++ function searcher, so upon launching my script I have 2 arguments, one for the directory and the second one as the function name. This is how my output looks like:
first arg: Projekt
first arg: iseven
Projekt/AX/include/ax.h
Projekt/AX/src/ax.cpp
h
p
Now my question is: how do can I save the line by line output as a variable, so that later on I can use var as a path, or to use var2 as a character to compare. My plan was to use IF() statements to determine the type, idea: IF(last_char == p){echo:"something"}What I've tried was this question: Capturing multiple line output into a Bash variable and then giving it an array. So my code looked like: "${var[0]}". Please explain how can I use my line output later on, as variables.
I'd use readarray to populate an array variable just in case there's spaces in your command's output that shouldn't be used as field separators that would end up messing up foo=( ... ). And you can use shell parameter expansion substring syntax to get the last character of a variable; no need for that awk bit in your var2:
#!/usr/bin/env bash
readarray -t lines < <(printf "%s\n" "Projekt/AX/include/ax.h" "Projekt/AX/src/ax.cpp")
for line in "${lines[#]}"; do
printf "%s\n%s\n" "$line" "${line: -1}" # Note the space before the -1
done
will display
Projekt/AX/include/ax.h
h
Projekt/AX/src/ax.cpp
p

How to assign a value to a variable which name is in a variable in bash?

I have a config file which looks like this:
$ cat .config
PARAM1 = avalue # a comment
PARAM2 = "many values" # another comment
# PARAM3=blabla
I wrote a function to read from it:
get_from_config_file()
{
A=$(grep "$1" ${config_file} | grep -v "^#" | sed s'/^[[:space:]]*//g' | sed s'/#.*$//' | sed s'/^.*=[[:space:]]*//' | sed s'/[[:space:]]*$//' | sed s'/"//g')
echo "$A"
}
Then I can read the parameters from the config file which works fine:
PARAM1=$(get_from_config_file "PARAM1")
PARAM2=$(get_from_config_file "PARAM2")
But I wanted to make it better (I have many parameters in this config file) so I wanted to be able to grab the value of all my parameters and then assign to variables in a simple for loop -- and here I got in trouble:
for name in PARAM1 PARAM2
do
value=$(get_from_config_file "$name")
echo $name, $value
# How to assign here $value to a variable named PARAM1, PARAM2 which is contained in name ?
# Note that I do not want to use an array for this
# param[$name]="$value"
done
Thanks,
Define variables directly using declare
for name in PARAM1 PARAM2
do
declare -gx "$name"="$(get_from_config_file "$name")"
#echo $name, $value
# How to assign here $value to a variable named PARAM1, PARAM2 which is contained in name ?
# Note that I do not want to use an array for this
# param[$name]="$value"
done
echo PARAM1="$PARAM1"
echo PARAM2="$PARAM2"
When you run this command, declare -gx "$name"="$value", Bash expands the variables, name and value, first. Then execute the command, declare -gx PARAM1=foobar
declare options:
-g create global variables when used in a shell function; otherwise
ignored
-x to make NAMEs export
for name in PARAM1 PARAM2
do
value=$(get_from_config_file "$name")
eval "$name"="$value"
done
This should assign the way you want.
Also for get_from_config_file how about,
awk -v input="$name" -F" = " '$0 ~ input{split($2, arr, "#"); print arr[1]}' .config
read is the command you are missing. while and read can be used together to read variables from a file. How you process the file to remove the comments is up to you; there are many ways. In the following example, I used sed to remove the # comments and convert the delimiter = to a single space.
sed '/^[[:blank:]]*#/d;s/#.*//;s/[[:blank:]]*=[[:blank:]]*/ /' "/.config" \
| while read -r name value; do
echo $name $value
done
If you remove the whitespaces around = signs the file can be interpreted as shell script:
. .config
If you don't want to edit the file:
eval "$(cat .config | sed 's/ = /=/')"

How do you split a string from shell-redirect or `read`?

I'm trying to split key value pairs (around an = sign) which I then use to edit a config file, using bash. But I need an alternative to the <<< syntax for IFS.
The below works on my host system, but when i log in to my ubuntu virtual machine through ssh I have the wrong bash version. Whatever I try, <<< fails. (I am definitely calling the right version of bash at the top of the file, using #!/bin/bash (and I've tried #!/bin/sh etc too)).
I know I can use IFS as follows on my host mac os x system:
var="word=hello"
IFS='=' read -a array <<<"$var"
echo ${array[0]} ${array[1]]}
#alternative -for calling through e.g. sh file.sh param=value
for var in "$#"
do
IFS='=' read -a array <<<"$var"
echo ${array[0]} ${array[1]]}
done
#alternative
IFS='=' read -ra array <<< "a=b"
declare -p array
echo ${array[0]} ${array[1]}
But this doesn't work on my vm.
I also know that I can should be able to switch the <<< syntax through backticks, $() or echo "$var" | ... but I can't get it to work - as follows:
#Fails
IFS='=' read -ra myarray -d '' <"$var"
echo ${array[0]} ${array[1]]}
#Fails
echo "$var" | IFS='=' read -a array
echo ${array[0]} ${array[1]]}
#fails
echo "a=b" | IFS='=' read -a array
declare -p array
echo ${array[0]} ${array[1]}
Grateful for any pointers as I'm really new to bash.
Your first failed attempt is because < and <<< are different operators. < opens the named file.
The second fails because read only sets the value of array in the subshell started by the pipe; that shell exits after the completion of the pipe, and array disappears with it.
The third fails for the same reason as the second; the declare that follows doesn't make any difference.
Your attempts have been confounded because you have to use the variable in the same sub-shell as read.
$ echo 'foo=bar' | { IFS='=' read -a array; echo ${array[0]}; }
foo
And if you want your variable durable (ie, outside the sub-shell scope):
$ var=$(echo 'foo=bar' | { IFS='=' read -a array; echo ${array[0]}; })
$ echo $var
foo
Clearly, it isn't pretty.
Update: If -a is missing, that suggests you're out of the land of arrays. You can try parameter substitution:
str='foo=bar'
var=${str%=*}
val=${str#*=}
And if that doesn't work, fall back to good ole cut:
str='foo=bar'
var=$(echo $str | cut -f 1 -d =)
val=$(echo $str | cut -f 2 -d =)

Remove a substring from a bash variable

A bash variable contents are command line arguments, like this:
args="file-1.txt file-2.txt -k file-3.txt -k --some-argument-1 --some-argument-2"
the string -k can appear anywhere in the above string, there are some other arguments that are not -k.
Is it possible to extract all the strings (i.e. file names with all other arguments) except -k from the argument, and assign it to a bash variable?
Using sed
Is is possible to extract all the strings (i.e. file names with all other arguments) except -k from the argument, and assign it to a bash variable?
I am taking that to mean that you want to remove -k while keeping everything else. If that is the case:
$ new=$(echo " $args " | sed -e 's/[[:space:]]-k[[:space:]]/ /g')
$ echo $new
file-1.txt file-2.txt file-3.txt --some-argument-1 --some-argument-2
Using only bash
This question is tagged with bash. Under bash, the use of sed is unnecessary:
$ new=" $args "
$ new=${new// -k / }
$ echo $new
file-1.txt file-2.txt file-3.txt --some-argument-1 --some-argument-2
Piping it to sed should work:
echo $args | sed -e 's/[[:space:]]\-[[:alnum:]\-]*//g'
file-1.txt file-2.txt file-3.txt
and you can assign it to a variable with:
newvar=`echo $args | sed -e 's/[[:space:]]\-[[:alnum:]\-]*//g'`
Command-line arguments in bash should be stored in an array, to allow for arguments that contain characters that need to be quoted.
args=(file-1.txt file-2.txt -k file-3.txt -k --some-argument-1 --some-argument-2)
To extract strings other than -k, just use a for loop to filter them.
newargs=()
for arg in "${args[#]}"; do
[[ $arg = "-k" ]] && newargs+=("$arg")
done

setting variables in bash script

I have the following command:
echo "exec [loc_ver].[dbo].[sp_RptEmpCheckInOutMissingTime_2]" |
/home/mdland_tool/common/bin/run_isql_prod_rpt_2.sh |
grep "^| Row_2" |
awk '{print $15 }'
which only works with echo in the front. I tried to set this line into a variable. I've tried quotations marks, parenthesis, and back ticks, with no luck.
May anyone tell me the correct syntax for setting this into a variable?
If you want more columns store in an array you should use this syntax (it is also good if you have only one result):
#!/bin/bash
result=( $( echo "exec [loc_ver].[dbo].[sp_RptEmpCheckInOutMissingTime_2]" |
/home/mdland_tool/common/bin/run_isql_prod_rpt_2.sh |
grep "^| Row_2" |
awk '{print $15 }' ) )
$result=$(exec [loc_ver].[dbo].[sp_RptEmpCheckInOutMissingTime_2]" | /home/mdland_tool/common/bin/run_isql_prod_rpt_2.sh | grep "^| Row_2" | awk '{print $15 })
Since you asked for both meanings of your question:
First, imagine a simpler case:
echo asdf
If you want to execute this command and store the result somewhere, you do the following:
$(echo asdf)
For example:
variable=$(echo asdf)
# or
if [ "$(echo asdf)" == "asdf" ]; then echo good; fi
So generally, $(command) executes command and returns the output.
If you want to store the text of the command itself, you can, well, just do that:
variable='echo asdf'
# or
variable="echo asdf"
# or
variable=echo\ asdf
Different formats depending on the content of your command. So now once you have the variable storing the command, you can simply execute the command with the $(command) syntax. However, pay attention that the command itself is in a variable. Therefore, you would execute the command by:
$($variable)
As a complete example, let's combine both:
command="echo asdf"
result=$($command)
echo $result

Resources