2

I have an array that contains variable names. In these variables I am assigning values using cycle. Then I am passing these variable names with assigned values ot another function, which checks valid input.

What I need to acomplish is to check if the variable's value contains specific symbol, and if it does, then truncate this value.

Example: when asked for "Admin gateway: " I enter for example value 192.168.1.254/20 (which is nonsense), I want this value to be truncated to 192.168.1.254

Following initialization $1="something" does not work, it returns error admGW=192.168.1.254: command not found

I have tried something like declare $1="something", but this will only create another local variable visible within current function. I need to reinitialize existing global variable instead. This is maybe not the best approach, but I'm curious if this kind of variable initialization is possible.

Sample code:

#!/bin/bash
read_variables(){
    all_vars_desc=("Admin IP/mask: " "Admin gateway: ")
    all_vars_name=("admIP" "admGW")

    for ((i=0; i<${#all_vars_desc[*]}; i++)); do
        read -p "${all_vars_desc[$i]}" ${all_vars_name[$i]}
        check_value ${all_vars_name[$i]} "${!all_vars_name[$i]}"
    done
}

check_value(){
    case $1 in
        *IP) ;; #some code
        *GW) if [[ "$2" == */* ]]; then
                 $1=$(echo "$2" | awk -F/ '{print $1}')
                 echo "Truncating to ${!1}"
             fi;;
    esac
}

read_variables
0

1 Answer 1

1

When you tried using the declare on $1 in your check_value() the variable definition is limited to local scope, but declare has a -g flag for making the variable global. Change the incorrect line

$1=$(echo "$2" | awk -F/ '{print $1}')

to

delcare -g "$1"=$(echo "$2" | awk -F/ '{print $1}')

See more about the declare built-in command.

I modified your script to print the elements at the end of the script like below and

for ((i=0; i<${#all_vars_name[*]}; i++)); do
    echo ${!all_vars_name[$i]}
done

Running now with debugger mode (bash -x), it produced the result as you needed,

$ bash -x script.sh
+ read_variables
+ all_vars_desc=("Admin IP/mask: " "Admin gateway: ")
+ all_vars_name=("admIP" "admGW")
+ (( i=0 ))
+ (( i<2 ))
+ read -p 'Admin IP/mask: ' admIP
Admin IP/mask: 1.1.1.1/32
+ check_value admIP 1.1.1.1/32
+ case $1 in
+ (( i++ ))
+ (( i<2 ))
+ read -p 'Admin gateway: ' admGW
Admin gateway: 2.2.2.2/32
+ check_value admGW 2.2.2.2/32
+ case $1 in
+ [[ 2.2.2.2/32 == */* ]]
++ echo 2.2.2.2/32
++ awk -F/ '{print $1}'
+ declare -g admGW=2.2.2.2
+ echo 'Truncating to 2.2.2.2'
Truncating to 2.2.2.2
+ (( i++ ))
+ (( i<2 ))
+ (( i=0 ))
+ (( i<2 ))
+ echo 1.1.1.1/32
1.1.1.1/32
+ (( i++ ))
+ (( i<2 ))
+ echo 2.2.2.2
2.2.2.2
+ (( i++ ))
+ (( i<2 ))

and in normal mode, to confirm the variable values are updated in the main function

$ bash script.sh
Admin IP/mask: 1.1.1.1/32
Admin gateway: 2.2.2.2/32
Truncating to 2.2.2.2
1.1.1.1/32
2.2.2.2

Since OP had a relatively older version of bash, and declare -g is available from bash 4.2 onwards only. In older bash versions, you can still remove the line with the declare and the subsequent line with indirect variable expansion and just do

eval "$(printf %s=%q "$1" "$(echo "$2" | awk -F/ '{print $1}')")"

Since you are using eval here, you need to be absolutely sure about sanitizing the right hand side correctly i.e. in a way knowing absolutely sure what you are passing in $2, see BashFAQ/006 under Assigning indirect/reference variables

Sign up to request clarification or add additional context in comments.

11 Comments

Thank you for answer. I have tried declare with attribute "-g" before too (sorry that I didn't mention it), but attribute "-g" is not present in my CentOS virtual machine. declare [-aAfFilrtux] [-p] [name[=value] ...]. I am not sure if it will be present on targeted system either. Isn't there any other way how to achieve expected result? "No" can also be an answer :D
@Lopfest: its not about the CentOS machine, you have an outdated bash version. Think you can upgrade it? Can you show us bash --version?
Sure. GNU bash, version 4.1.2(2)-release (x86_64-redhat-linux-gnu)
@Lopfest: Refer my update, which might work for you in your bash version
Don't use awk here; just use parameter substitution. declare -g "$1=${2%%/*}"
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.