简体   繁体   English

用sed修改bash变量

[英]Modify bash variables with sed

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". 为此,我尝试使用bash循环,该循环遍历用“ 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仅包含存储为字符串的环境变量的名称。 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. 基本问题是如何正确提供环境变量本身给sed。

Any ideas how to properly modify my script are welcome. 欢迎提供任何有关如何正确修改脚本的想法。

Thanks, Alex 谢谢,亚历克斯

Part I 第一部分

The way you're parsing env is wrong . 您解析env错误的 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 . 并且您很可能会看到env的输出有所不同。

Now the while method I gave will also break when you have newlines in your variables. 现在, while变量中包含换行符时,我给出的while方法也会中断。

Very likely your env version has the flag -0 or --null . 您的env版本很可能带有标志-0--null Use it to be 100% safe: 使用它是100%安全的:

while IFS= read -r -d '' line; do
    # do stuff with variable line
done < <(env --null)

Part II 第二部分

When you have read your line, you want to split it into a key and a value. 读完行后,您想将其拆分为键和值。 Don't use awk for that. 不要使用awk。 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)

Part III 第三部分

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 . 现在,我了解到您只想对包含字符串ipo的变量执行操作,对于这些变量,您想要用空格替换字符串-ipo-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)

Part IV 第四部分

You want to replace the variable with this new value. 您要用此新值替换变量。 You can use declare for this. 您可以为此使用declare (You don't need the export builtin, since your variable is already marked as exported): (您不需要内置的export ,因为您的变量已被标记为已导出):

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)

Part V 第五部分

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 ,请使用:

. file

(yes, a dot, a space and the name of the file). (是,点,空格和文件名)。

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

I think the bit you are missing is the ${!i} to expand the variable called whatever $i is set to.. 我认为您缺少的是${!i}来扩展名为$i设置为的变量。

#!/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.

我相信您可以在awk中完成所有操作:

env | grep ipo | awk -F= '{ gsub("-ipo","",$2); gsub("-axAVX","",$2); print $0}'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM