LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Bash script issue (https://www.linuxquestions.org/questions/linux-newbie-8/bash-script-issue-4175555326/)

kingston 10-05-2015 10:22 AM

Bash script issue
 
Hi Guru

Following is part of a script which is being written to automate one of our work, but i couldn't be successful on getting the result i expected. Can someone help?

Code:

#!/bin/bash

DB="ORADB"
FDB="ORADB001"
LDB="ORADB009"

FDB_N=`echo $FDB | awk -F "$DB" '{print $2}'`
LDB_N=`echo $LDB | awk -F "$DB" '{print $2}'`

TD=`echo $FDB_N |wc -c`
TD_1=`expr $TD - 1`

BEGIN=$(echo $FDB_N | sed 's/^00\?//')
END=$(echo $LDB_N | sed 's/^00\?//')

TND=`expr $(expr $END - $BEGIN) + 1`
echo $TND
j=1

while [[ $j -le $TND ]]
do
for ((i=$BEGIN; i<=$END; i++)); do
#    printf $DB"%0"$TD_1"d%s\n" $i
            DB$j=$(printf $DB"%0"$TD_1"d%s\n" $i)
done
j=((j++))
don

I want my script to store the output as variables. This is required as this output would be inputs to complete the actual task of my script.
Code:

DB1=ORADB001
------------
------------
DB9=ORADB009

Can someone correct my script?

szboardstretcher 10-05-2015 10:35 AM

First off - are you trying to set variables from this bash script? Or are you trying to output it to a file, which can then be used to set the variables?

HMW 10-05-2015 10:36 AM

Hi!

I honestly have to admit that I don't understand the logic in your script. Not saying it is bad, mind you, I just don't get it!

However... this:
Code:

j=((j++))
Doesn't work. To increment a variable i Bash, do like this:
Code:

i=$(($i+1))
As for the rest... I don't really know!

Best regards,
HMW

szboardstretcher 10-05-2015 10:39 AM

Quote:

Originally Posted by HMW (Post 5430180)
Hi!

To increment a variable i Bash, do like this:
Code:

i=$(($i+1))
As for the rest... I don't really know!

Best regards,
HMW

If its specifically BASH - then the accepted paradigm is:

Code:

let i++
#or
((i++))

But your method is more portable to other shells.

And of course this has been discussed: http://www.linuxquestions.org/questi...sh-4175437116/

HMW 10-05-2015 11:05 AM

Quote:

Originally Posted by szboardstretcher (Post 5430183)
But your method is more portable to other shells.

Good to know, thanks! Actually, the main reason I use ”my” method is that it is the one I remember!!!

Shadow_7 10-05-2015 11:20 AM

Variables are local to the script. Unless you "export" them.

So...

Code:

export DB$j=$(printf $DB"0"$TD_1"d%s\n" $i)
or not. And I'm not sure why you're mixing $() and ``, just use $() for consistency. Both technically do the same thing. At least in theory.

kingston 10-06-2015 05:46 AM

Thank you all for helping me on this.

@szboardstretcher: I am trying to set the variables and the value of these variables will be used as final result of this script

@HMW: Yes, i was wrong. I corrected in the script.

@shadow 7: Not aware that $() and `` does the same thing. I thought the commands enclosed in `` will be executed first and this can be enclosed in $() too. Please correct me if i am wrong. As far as the variables are concerned, i would like to keep it local to the script. But i am working on specific part of the script.
This portion of the script should give output as DB1=DB001, and DB2=DB002 (obviously, as per the inputs given in the script) But i have a doubt on setting the variable name itself. "DBN$j" is this the right bash variable name?

Modified script:
Code:

#!/bin/bash

DB="TS1SPM"
FDB="TS1SPM001"
LDB="TS1SPM009"

FDB_N=$(echo $FDB | awk -F "$DB" '{print $2}')
LDB_N=$(echo $LDB | awk -F "$DB" '{print $2}')

TD=$(echo $FDB_N |wc -c)
TD_1=$(expr $TD - 1)

BEGIN=$(echo $FDB_N | sed 's/^00\?//')
END=$(echo $LDB_N | sed 's/^00\?//')

TND=`expr $(expr $END - $BEGIN) + 1`
echo $TND
j=1

for ((i=$BEGIN; i<=$END; i++)); do
    printf $DB"%0"$TD_1"d%s\n" $i
            export DBN$j=$(printf $DB"%0"$TD_1"d%s\n" $i)
            echo -e "DBN$j exported"
                if  [[ $j -le $TND ]]
                        then
                                ((j++))
                        else
                                :
                fi
#echo -e "DB$j=$DBN$j"
echo $(DBN$j)
done

Script output is:
Code:

TS1SPM001
DBN1 exported
./test1: line 31: DBN2: command not found

TS1SPM002
DBN2 exported
./test1: line 31: DBN3: command not found

TS1SPM003
DBN3 exported
./test1: line 31: DBN4: command not found

TS1SPM004
DBN4 exported
./test1: line 31: DBN5: command not found

TS1SPM005
DBN5 exported
./test1: line 31: DBN6: command not found

TS1SPM006
DBN6 exported
./test1: line 31: DBN7: command not found

TS1SPM007
DBN7 exported
./test1: line 31: DBN8: command not found

TS1SPM008
DBN8 exported
./test1: line 31: DBN9: command not found

TS1SPM009
DBN9 exported
./test1: line 31: DBN10: command not found


grail 10-06-2015 06:12 AM

Quote:

I thought the commands enclosed in `` will be executed first and this can be enclosed in $() too.
There is not set precedence except for the fact the shell will expand all items working from the inside out. The main advantage of $(), apart from being clearer IMO, is that they can be nested.
So you can do $(cmd1 $(cmd2)), but `cmd1 `cmd2`` will fail

As for your code, I would perhaps looking at doing most of it with just bash as the calls to outside commands like awk and sed are not really needed.
So I have commented out your original pieces and put in what I would have done:
Code:

#!/usr/bin/env bash

DB="TS1SPM"
FDB="TS1SPM001"
LDB="TS1SPM009"

FDB_N=${FDB#$DB} #(echo $FDB | awk -F "$DB" '{print $2}')
LDB_N=${LDB#$DB} #(echo $LDB | awk -F "$DB" '{print $2}')

TD=${#FDB_N} #(echo $FDB_N |wc -c)
(( TD_1 = --TD )) #$(expr $TD - 1)

BEGIN=${FDB_N##*)} #(echo $FDB_N | sed 's/^00\?//')
END=${LDB_N##*0}  #(echo $LDB_N | sed 's/^00\?//')

(( TND = END - BEGIN + 1 )) #`expr $(expr $END - $BEGIN) + 1`
echo $TND
j=1

for (( i = BEGIN; i <= END; i++ )); do
        printf "$DB0${TD_1}ds\n" $i
        DBN[j]=$(printf "$DB%0${TD_1}d%s\n" $i)
        echo -e "DBN[$j] exported"
        :<<-"COMMENT"
        if  [[ $j -le $TND ]]
        then
                ((j++))
        else
                :
        fi
        COMMENT
#        (( j <= TND )) && (( j++ ))

        #echo -e "DB$j=$DBN$j"
        echo "${DBN[j]}" #$(DBN$j)
        (( j <= TND )) && (( j++ ))
done

An important note at the end, if you increase 'j' prior to the echo you will get nothing as the new 'j' has not been assigned yet.

Hope that helps :)

Shadow_7 10-06-2015 08:02 AM

A variable array is probably better suited than a variable variable name.

http://www.tldp.org/LDP/abs/html/arrays.html

But that means that your
Code:

DB1=ORADB001
------------
------------
DB9=ORADB009

Will become
Code:

DB[1]=ORADB001
------------
------------
DB[9]=ORADB009

Otherwise you might enclose the variable variable name in "" so it gets interpreted before it is assigned a value. So...
Code:

DBN$j=$(printf $DB"0"$TD_1"d%s\n" $i)
becomes
Code:

"DBN$j"=$(printf $DB"%0"$TD_1"d%s\n" $i)
or
Code:

DBN[$j]=$(printf $DB"%0"$TD_1"d%s\n" $i)
the later-est of which is most likely to actually work. Although I haven't tested any of those to verify.

HMW 10-06-2015 10:57 AM

Quote:

Originally Posted by Shadow_7 (Post 5430705)
A variable array is probably better suited than a variable variable name.

Yeah, I agree. Using an array seems to be the best solution.

Edit: I see that grail has used that approach in his solution above.

kingston 10-07-2015 08:04 AM

Thanks again Grail, Shadow 7 and HMW.

@Grail: Your script is much powerful yet simple. I have to learn a lot to write a script as yours.
I will mark this thread as resolved.


All times are GMT -5. The time now is 12:23 AM.