我有一个名为replace.run
的脚本,其调用方式类似于:
$ replace.run 10
此文件包含:
char="pre casentext xskey=001 nREADYn"
i=2
while [ $i -le $1 ]; do
char="$char pre casentext xskey=00$i nREADYn"
i=$((i+1))
done
问题是
$char=pre casentext xskey=001 nREADYn pre casentext xskey=002 nREADYn pre casentext xskey=003 nREADYn pre casentext xskey=004 nREADYn pre casentext xskey=005 nREADYn pre casentext xskey=006 nREADYn pre casentext xskey=007 nREADYn pre casentext xskey=008 nREADYn pre casentext xskey=009 nREADYn pre casentext xskey=0010 nREADYn
如您所见,READYn
和pre case
之间有一个空格。这个空间是不需要的。任何帮助摆脱它将是非常受欢迎的。我尝试了类似的东西
echo $char|sed 's/ pre case/pre case/' >char
但这显然是一团糟。
据我了解,您拥有此额外空间的原因是以下歧义:
# BUG: this expands $charpre instead of $char
char="$charpre casentext xskey=00$i nREADYn"
有几种方法可以避免这种情况:
# FIX: use ${} to allow the new "pre" to be immediately after prior content
char="${char}pre casentext xskey=00$i nREADYn"
。或。。。
# FIX: use += to append without expanding old content
char+="pre casentext xskey=00$i nREADYn"
也就是说,完全不同的方法可能更有意义:
lines=( )
for ((i=1; i<=$1; i++)); do
printf -v xskey '%03d' "$i" # format as 0-padded 3-digit value
lines+=( "precase" "text xskey=$xskey" "READY" )
done
printf '%sn' "${lines[@]}"
这会将您的行收集在一个数组中,而不是单个字符串中,从而为您提供更详细的控制。它还确保当您的计数器超过 9 时,您会得到 text ksey=010
,而不是text xskey=0010
。
如果您真的想要 n
s 而不是换行符,您可以通过更改最后一行来进行更改:
# ...if you want to put "n" strings, not literal newlines, in output:
printf '%s\n' "${lines[@]}"
>
重定向到文件。所以你现在得到了一个名为 char
的文件。
您可以使用命令替换来捕获变量中命令的输出:
char=$(sed 's/pre case/precase/' <<< "$char")
永远记住在变量展开两边加上双引号,"$char"
而不是$char
不过,您根本不需要使用 sed:
char="${char/pre case/precase}"
顺便说一句,n
不是 bash 字符串中的换行符。您可以使用以下 c 字符串语法$'...'
。这将使用 C 转义序列,例如:
% echo "anb"
anb
% echo $'anb'
a
b