Reputation: 808
I am trying to modify a number of environmental variables containing predefined compiler flags. To do so, I tried using a bash loop that goes over all environmental variables listed with "env".
for i in $(env | grep ipo | awk 'BEGIN {FS="="} ; { print $1 } ' )
do echo $(sed -e "s/-ipo/ / ; s/-axAVX/ /" <<< $i)
done
This is not working since the loop variable $i contains just the name of the environmental variable stored as a character string. I tried searching a method to convert a string into a variable but things started becoming unnecessary complicated. The basic problem is how to properly supply the environmental variable itself to sed.
Any ideas how to properly modify my script are welcome.
Thanks, Alex
Upvotes: 1
Views: 381
Reputation: 7959
I believe you can do it all in awk:
env | grep ipo | awk -F= '{ gsub("-ipo","",$2); gsub("-axAVX","",$2); print $0}'
Upvotes: 0
Reputation: 46813
The way you're parsing env
is wrong. It breaks whenever you have spaces or wildcards. Instead use this:
while IFS= read -r line; do
# do stuff with variable line
done < <(env)
To see why your solution is broken, do:
for i in $(env); do
echo "$i"
done
and you'll very likely see a difference with the output of env
.
Now the while
method I gave will also break when you have newlines in your variables.
Very likely your env
version has the flag -0
or --null
. Use it to be 100% safe:
while IFS= read -r -d '' line; do
# do stuff with variable line
done < <(env --null)
When you have read your line, you want to split it into a key and a value. Don't use awk for that. Use Bash:
key=${line%%=*}
value=${line#*=}
Look:
while IFS= read -r -d '' line; do
key=${line%%=*}
value=${line#*=}
echo "key: $key"
echo "value: $value"
done < <(env --null)
Now I understand that you want to act only on the variables that contain the string ipo
, and for these you want to substitute a space for the first occurence of the string -ipo
and -axAVX
. So:
while IFS= read -r -d '' line; do
key=${line%%=*}
value=${line#*=}
[[ $value = *ipo* ]] || continue
value=${value/-ipo/ }
value=${value/-axAVX/ }
echo "key: $key"
echo "new value: $value"
done < <(env --null)
You want to replace the variable with this new value. You can use declare
for this. (You don't need the export
builtin, since your variable is already marked as exported):
while IFS= read -r -d '' line; do
key=${line%%=*}
value=${line#*=}
[[ $value = *ipo* ]] || continue
value=${value/-ipo/ }
value=${value/-axAVX/ }
declare "$key=$value"
done < <(env --null)
Finally, you'll try to put this in a script and you'll realize that it doesn't work: that's because a script is executed in a child process and every changes made in a child process are not seen by the parent process. So you'll want to source it! To source a file file
, use:
. file
(yes, a dot, a space and the name of the file).
Upvotes: 3
Reputation: 4396
I think the bit you are missing is the ${!i}
to expand the variable called whatever $i
is set to..
#!/bin/sh
for i in $(env | grep ipo | awk 'BEGIN {FS="="} ; { print $1 }' )
do
val=$(sed -e "s/-ipo/ / ; s/-axAVX/ /" <<< ${!i})
export ${i}=${val}
echo ${i} is now set to $val
done
... do stuff with new env variables
If you run the script it will change the environment variable for itself and anything it spawns. When it returns however you will still have the same environment you started with.
$ echo $IPOVAR
blah -ipo -axAVX end # variable stats as this
$ sh env.sh
IPOVAR is now set to blah end # It is changed!
$ echo $IPOVAR
blah -ipo -axAVX end # Its still the same.
Upvotes: 1
Reputation: 4952
Try with indirect expansion:
for i in $(env | grep ipo | awk 'BEGIN {FS="="} ; { print $1 } ' )
do
echo $(sed -e "s/-ipo/ / ; s/-axAVX/ /" <<< ${!i})
done
Upvotes: 2