Register
It is currently Fri Oct 31, 2014 9:21 pm

Embeded variables


All times are UTC - 6 hours


Post new topic Reply to topic  [ 12 posts ] 
Author Message
 PostPosted: Wed Jul 13, 2011 8:50 am   

Joined: Wed Jul 13, 2011 8:43 am
Posts: 3
I have the following script (put together as an example) that I'm trying to get working but I'm not sure it can be done.

Code:
#!/usr/bin/env bash

envs="dev stage prod shared"
wdir='/some/${env}/folder/'

echo -n "Are you sure you wish to do something with '${envs}'? [Y|n] "
read answer

if [ "${answer}" == "Y" -o "${answer}" == "y" ] ; then
    for env in $envs
    do
        echo "${wdir}"
    done
fi


I know that I could simply have put the wdir assignment in the for loop which I did originally but, to make the script as easy to read as possible I'd like to assign all user changing variabes at the top... It's like a template string that I need to have expanded upon execution.

Can this be done or am I dreaming in bash?


Top
 Profile  
 PostPosted: Wed Jul 13, 2011 9:24 am   
Moderator
User avatar

Joined: Wed May 03, 2006 2:05 pm
Posts: 242
Of COURSE it can be done! It's just a matter of figuring out the way that works best for you :)

You could try something with sed, like this:
Code:

#!/usr/bin/env bash

envs="dev stage prod shared"
wdir="/some/REPLACE_ME/folder/"

echo -n "Are you sure you wish to do something with '${envs}'? [Y|n] "
read answer

if [ "${answer}" == "Y" -o "${answer}" == "y" ] ; then
    for env in $envs
    do
        newdir=$(echo ${wdir}|sed "s/REPLACE_ME/${env}/g")
        echo "${newdir}"
    done
fi


OR like you mentioned, you could set the $wdir variable in the loop, but use a prefix and suffix that you set at the top of the script. Something like this:
Code:

#!/usr/bin/env bash

envs="dev stage prod shared"
prefix="some"
suffix="folder"

echo -n "Are you sure you wish to do something with '${envs}'? [Y|n] "
read answer

if [ "${answer}" == "Y" -o "${answer}" == "y" ] ; then
    for env in $envs
    do
        wdir="/${prefix}/${env}/${suffix}/"
        echo "${wdir}"
    done
fi


I hope this helps! There are probably dozens of other ways that would work too!


Top
 Profile YIM  
 PostPosted: Wed Jul 13, 2011 3:00 pm   
User avatar

Joined: Wed Jun 08, 2011 8:27 am
Posts: 189
Location: outer Shpongolia
I don't really get the point of doing that.

If you want to make the script as easy to read as possible, then just define your variable at the
top of your script ( i.e., wdir= ) and write a comment telling what it does. Then, in your case,
define wdir directly in the for loop.

Also, for is used to iterate arguments, not strings, neither outputs.
Since you're using bash(1), you can use an array, i.e., envs=(dev stage prod shared).

Code:
#!/bin/bash

envs=(dev stage prod shared)
wdir=  # path to dir

read -rp "Are you sure you wish to do something with $(IFS=,; echo "${envs[*]}")? [Y/n] "

if [[ $REPLY = [yY] ]]; then
    for env in "${envs[@]}"; do
        echo "/some/$env/dir"
    done
fi


And as pointed out jeo, if you really want to do that, then define wdir with a default
env string, and replace it in the loop.

Code:
#!/bin/bash

envs=(dev stage prod shared)
wdir=/some/ENV_DEFAULT/dir

read -rp "Are you sure you wish to do something with $(IFS=,; echo "${envs[*]}")? [Y/n] "

if [[ $REPLY = [yY] ]]; then
    for env in "${envs[@]}"; do
        echo "${wdir/ENV_DEFAULT/$env}"
    done
fi


Top
 Profile  
 PostPosted: Thu Jul 14, 2011 1:29 am   
User avatar

Joined: Tue Apr 27, 2010 2:28 pm
Posts: 172
Location: Czech Republic
jsz wrote:
Also, for is used to iterate arguments, not strings, neither outputs.

OK. What is there to iterate strings and outputs, then? :)


Top
 Profile  
 PostPosted: Thu Jul 14, 2011 1:42 am   

Joined: Wed Jul 13, 2011 8:43 am
Posts: 3
Thanks jeo - you're solution worked perfectly :))


Top
 Profile  
 PostPosted: Thu Jul 14, 2011 8:36 am   
Moderator
User avatar

Joined: Wed May 03, 2006 2:05 pm
Posts: 242
Glad to be of service!


Top
 Profile YIM  
 PostPosted: Thu Jul 14, 2011 3:07 pm   
User avatar

Joined: Wed Jun 08, 2011 8:27 am
Posts: 189
Location: outer Shpongolia
choroba wrote:
jsz wrote:
Also, for is used to iterate arguments, not strings, neither outputs.

OK. What is there to iterate strings and outputs, then? :)


You use an array to iterate strings and a while loop with read(0) to iterate commands output.

Code:
array=(foo bar baz)

for element in "${array[@]}"; do
    ... "$element"
done


while read -r; do
    ... "$REPLY"
done < <(command)


If you're writing POSIX sh(1), then you'd have to use set(0), a pipe, and a subshell ( if your loop is large ) to read commands output.

Code:
set -- foo bar baz

for element in "$@"; do
    ... "$element"
done


command |
(
    while IFS= read -r line; do
        ... "$line"
    done

    ...
)


Top
 Profile  
 PostPosted: Mon Apr 02, 2012 5:41 pm   

Joined: Mon Feb 16, 2009 10:07 am
Posts: 19
Location: Paris - France
well, if I have a space separated list of (spaceless!) items, why should I first make an array of this list and then iterate through that array
instead of just like in good old times iterate through that list ?

Quote:
jsz
Code:
array=(foo bar baz)

for element in "${array[@]}"; do
    ... "$element"
done


Code:
for item in $list ; do
   ..."$item"
done


this WORKS and is FASTER - not that much, but you know how I am eager to save time :)


Top
 Profile ICQ YIM  
 PostPosted: Tue Apr 03, 2012 10:52 am   
User avatar

Joined: Wed Jun 08, 2011 8:27 am
Posts: 189
Location: outer Shpongolia
You should do it to make it safer.

Of course, if you know your "list" content it's pointless, but it's a good habit to have.

Code:
$ mkdir dir
$ cd dir/
$ touch file
$ list='foo bar * baz'; for e in $list; do echo "$e"; done
foo
bar
file
baz


Top
 Profile  
 PostPosted: Tue Apr 03, 2012 12:36 pm   

Joined: Mon Feb 16, 2009 10:07 am
Posts: 19
Location: Paris - France
Code:
$ a=(foo bar * baz)
$ echo "${a[@]}"
foor bar file baz

not much safer :(


Top
 Profile ICQ YIM  
 PostPosted: Tue Apr 03, 2012 7:56 pm   

Joined: Mon Feb 16, 2009 10:07 am
Posts: 19
Location: Paris - France
sorry, I should have been more rigorous :
Code:
$ mkdir dir
$ cd dir
$ touch file
$ a=(foo bar * baz)
$ for i in "${a[@]}" ; do echo "$i" ; done
foo
bar
file
baz


Top
 Profile ICQ YIM  
 PostPosted: Wed Apr 04, 2012 2:14 am   

Joined: Mon Feb 16, 2009 10:07 am
Posts: 19
Location: Paris - France
but of course you're right : arrays are basically safer and must be used if you're not sure that each item in the list will not collide with the aimed result. Just : sometimes you can be sure.


Top
 Profile ICQ YIM  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
cron


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP