Bash变量替换和字符串 [英] Bash variable substitution and strings

查看:100
本文介绍了Bash变量替换和字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两个变量:

  a ="AAA"b ="BBB" 

我从文件中读取了一个字符串.该字符串如下:

  str ='$ a $ b' 

如何从第一个替换变量的字符串创建新字符串?

  newstr ="AAA BBB" 

解决方案

@godblessfq 询问:

如果str包含换行符,该如何替换并在输出中保留换行符?

因此,这不是健壮,因为每个间接变量必须必须与所有特殊字符分隔成第一个,最后一个或空格

  str = $'$ var1 world!\ n ...第二行...'var1 =你好newstr =()设置-fIFS =''读取-d $'\ 377'-ra数组<<<"$ str"对于"$ {array [@]}"中的cnt;执行["$ {cnt:0:1}" =='$']&&cnt = $ {cnt:1}&&cnt = $ {!cnt}newstr + =("$ cnt")完毕设置+ fnewstr ="$ {newstr [*]}"回声"$ newstr"你好,世界!第二行 

由于<<< 内联字符串添加尾随换行符,因此可以编写最后一个 echo 命令:

  echo"$ {newstr%$'\ n'}" 

Let's say I have two variables:

a="AAA"
b="BBB"

I read a string from a file. This string is the following:

str='$a $b'

How to create a new string from the first one that substitutes the variables?

newstr="AAA BBB"

解决方案

variable indirection whithout eval:

Well, as eval is evil, we may try to make this whithout them, by using indirection in variable names.

 a="AAA"
 b="BBB"
 str='$a $b'

 newstr=()
 for cnt in $str ;do
     [ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt}
     newstr+=($cnt)
   done
 newstr="${newstr[*]}"

 echo $newstr
 AAA BBB

Another try:

var1="Hello"
var2="2015"

str='$var1 world! Happy new year $var2'

newstr=()
for cnt in $str ;do
    [ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt}
    newstr+=($cnt)
  done
newstr="${newstr[*]}"

echo $newstr 
Hello world! Happy new year 2015

Addendum As correctly pointed by @EtanReisner's comment, if your string do contain some * or other glob expendable stings, you may have to use set -f to prevent bad things:

cd /bin
var1="Hello"
var2="star"
var3="*"
str='$var1 this string contain a $var2 as $var3 *'

newstr=()
for cnt in $str ;do
     [ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt};
     newstr+=("$cnt");
   done;
newstr="${newstr[*]}"

echo "$newstr"
Hello this string contain a star as * bash bunzip2 busybox....zmore znew

echo ${#newstr}
1239

Note: I've added " at newstr+=("$cnt"); to prevent glob expansion, but set -f seem required...

newstr=()
set -f
for cnt in $str ;do
    [ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt}
    newstr+=("$cnt")
  done
set +f
newstr="${newstr[*]}"

echo "$newstr"
Hello this string contain a star as * *

Nota 2: This is far away from a perfect solution. For sample if string do contain ponctuation, this won't work again... Example:

str='$var1, this string contain a $var2 as $var3: *'

with same variables as previous run will render: ' this string contain a star as *' because ${!var1,} and ${!var3:} don't exist.

... and if $str do contain special chars:

As @godblessfq asked:

If str contains a line break, how do I do the substitution and preserve the newline in the output?

So this is not robust as every indirected variable must be first, last or space separated from all special chars!

str=$'$var1 world!\n... 2nd line...'
var1=Hello
newstr=()
set -f
IFS=' ' read -d$'\377' -ra array <<<"$str"
for cnt in "${array[@]}";do
    [ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt}
    newstr+=("$cnt")
  done
set +f
newstr="${newstr[*]}"

echo "$newstr"
Hello world!
... 2nd line...

As <<< inline string add a trailing newline, last echo command could be written:

echo "${newstr%$'\n'}"

这篇关于Bash变量替换和字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆