如何在Bash中用Sed将字符串所有字符替换为ASCII码?
问题描述
我写了下面这段代码,但运行结果不符合预期:
w(){ echo $(printf "%d" "'$1") } echo $(w "a") t="abcd" echo "$t" | sed "s/./(w &)/g" echo "$t" | sed "s/./$(w &)/g"
实际运行输出:
97 (w a)(w b)(w c)(w d) 0000
我想要的输出是:
979899100
试过给w或者$(w &)加单/双引号,都没用,到底忽略了什么?
补充编辑
后来查到export -f w,试了之后又遇到新问题,网上找不到解释:
第一段测试代码
function w(){ echo $(printf "%d" "'$1") } export -f w t="abcd" echo $t | sed 's/./w &/eg'
输出只有:
97
为什么g全局替换选项没生效?
第二段测试代码
function w(){ echo $(printf "%d" "'$1") } export -f w t="abcd" echo $t | sed 's/./$(w &)/eg'
这次输出报错:
/bin/sh: 979899100: command not found
为什么第二段会报“command not found”,第一段却不会?是不是因为用了$(..)求值?
附言:我是不是该开个新问题?
问题解答
原始问题的核心原因
- 第一个
sed "s/./(w &)/g":双引号包裹的内容里,w &只会被当作普通字符串替换,不会触发函数执行,所以输出的是(w a)这类字面内容。 - 第二个
sed "s/./$(w &)/g":双引号会让$(w &)先被shell解析——这里的&是shell的后台执行符号,不是sed的匹配引用,所以w &实际是把w函数后台运行且无有效参数,printf "%d" "'"的结果是0,最终所有字符都被替换成0,输出0000。
关于export -f w后的两个问题
为什么g选项没生效?
sed的e选项会把替换后的内容当作命令执行,但你的w函数里用了echo,每个字符处理后都会输出换行。当第一个字符a处理完输出97\n,sed会把这个输出作为下一轮处理的输入,剩下的bcd根本没被处理,所以只输出97。
解决办法:让w函数不要输出换行,直接用printf代替echo:
function w(){ printf "%d" "'$1" } export -f w t="abcd" echo "$t" | sed 's/./w &/eg'
这样每个字符处理后输出的数字没有换行,sed会继续处理后续字符,最终得到你想要的979899100。
为什么第二段代码报“command not found”?
sed的e选项会把整行替换后的结果当作一个完整命令交给shell执行。你写的s/./$(w &)/eg,替换后整行变成$(w a)$(w b)$(w c)$(w d),shell会先把所有$(...)展开求值,得到纯数字字符串979899100,然后尝试把这个字符串当作命令执行——显然系统里没有这个命令,所以报错。
而第一段代码s/./w &/eg,替换后是w a w b w c w d,shell执行这个命令时,w函数只会读取第一个参数a,输出对应的ASCII码97,后面的参数被忽略,所以只输出97。
内容的提问来源于stack exchange,提问作者joel76
相关产品推荐
相关产品推荐

