Bash将脚本参数插入到字符串中

时间:2017-03-07 23:50:58

标签: c bash shell replace

因为一个问题我很累: 我想运行一个bash脚本,自动创建另一个bash脚本,该脚本反过来应该已经包含C代码,它只是在其输出通过管道传输到播放时动态编译和运行。 我的示例基于ComputerPhile bitshift variations code

我有一个像这样的C脚本(应该被替换并在以后开发):

g(i, x, t, o) {
    return ((3 & x & (i * (
        (3 & i >> 16 ? "BY}6YB6%" : "Qj}6jQ6%")[t%8] + 51
    ) >> o)) << 4);
};

main(i, n, s) {
    for (i = 0; ;i++)
        putchar(
            g(i, 1, n = i >> 14, 12) +
            g(i, s = i >> 17, n^i >> 13, 10) +
            g(i, s/3, n + ((i >> 11) % 3), 10) +
            g(i, s/5, 8 + n - ((i >> 10) % 3), 9)
        );
}

我想  1.缩小它  2.将"个字符转义为\" 得到这样的bash脚本:

#!/bin/bash
echo "g(i,x,t,o){return((3&x&(i*((3&i>>16?\"BY}6YB6%\":\"Qj}6jQ6%\")[t%8]+51)>>o))<<4);};main(i,n,s){for(i=0;;i++)putchar(g(i,1,n=i>>14,12)+g(i,s=i>>17,n^i>>13,10)+g(i,s/3,n+((i>>11)%3),10)+g(i,s/5,8+n-((i>>10)%3),9));}"|gcc -xc -&&./a.out|aplay

然而,我似乎无法接近那个目标。要么它会创建一个空字符串(echo ""|gcc ...),要么奇怪地将脚本参数粘贴到(...return ((3 & x & (i c2sh.sh tmp waveform.c waveform.sh ( (3 & i >> 16 ? BY}6YB6%...中,但我已经有一个版本,其中"被正确替换了。< / p>

我的代码(没有清理,所以你可以看到我尝试的其他两件事)目前是:

#!/bin/bash

echo '#!/bin/bash' > tmp

out=''

echo $(cat waveform.c | tr '"' ' ')

#while read line; do 
#    out+="$line"
#done < 'waveform.c'

#out=$(echo $out | sed 's/"/\\"/g')
out=${out/"/\\"}

echo 'echo "'$out'" | gcc -xc -&& ./a.out | aplay' >> tmp

mv tmp 'waveform.sh'
chmod +x 'waveform.sh'

到底发生了什么,应该如何正确地完成?

2 个答案:

答案 0 :(得分:3)

正确? 不应该完成。在bash中,代码生成是一种“气味”,与公认的最佳实践相反。

但是,无论如何你都要这样做,让shell进行转义,而不是试图编写自己的逻辑(几乎毫无例外地容易出现shell注入漏洞):

#!/bin/bash
infile=${1:-waveform.c}           # read name from command-line argument if given
content=$(<"$infile")             # $(<foo) is more efficient than $(cat foo)
content=${content//[[:space:]]/}  # trim spaces from variable contents

# put the arguments to the command you want to generate into an array
cmd=( printf '%s\n' "$content" )

# tell the shell to generate a string which has each element of that array escaped
printf -v cmd_q '%q ' "${cmd[@]}"

# put our generated contents into an array, one line per each;
# not essential, but makes it easy to comment each line we generate below.
output=(
  '#!/bin/bash'                  # using bash ensures that printf %q-generated code works.
  "$cmd_q | gcc -xc - || exit"   # use our generated string for all non-constant code.
  './a.out | aplay'
)
printf '%s\n' "${output[@]}"     # finally, emit output with all of the above

注意事项:

  • printf '%q'以这样的方式格式化给定的shell变量:当shell评估它时,它将评估回原始的文字内容。这不仅对于正确性而且对于安全性至关重要:如果您正在从别人的代码中听取波形,那么您不希望shell评估/* $(rm -rf ~) */
  • echo是一个非常模糊指定的命令,以便允许各种历史操作系统完全不同的实现符合the spec。正如POSIX建议的那样,在任何情况下,如果数据不是手工生成的,并且已知不会触发任何歧义,则应使用printf

答案 1 :(得分:0)

GitHub上有一个有用的C Minifier * python脚本,minifier.py,这可能有所帮助:

code=`python minifier.py waveform.c`
echo "$code" ## `printf "%s\n" "$code"` is safer though...

输出:

  

g(i,x,t,o){return((3&amp; x&amp;(i *((3&amp; i&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&n;&n;&n;&n;&n;&n;&n;&n;&n;&n;&n;&#;;   &#34; QJ} 6jQ6%&#34;)[吨%8] 51)GT;&GT;○))≤;&LT; 4);};主(I,N,S){对于(I = 0 ;;我++)的putchar(按g(i,1,N =&GT;&GT; 14,12)+ G(I,S = I&GT;&GT; 17,N ^ I&GT;&GT; 13,10)+ G(ⅰ ,S / 3,N +((I&GT;&GT; 11)%3),10)+ G(I,S / 5,8 + N - ((I&GT;→10)%3),9));}

对于更一般的修复C. Duffy's answer引用每个字符, 100%增加,使用某种binary to hex encoding会更有效,尽管对人类毫无意义,例如:

python minifier.py waveform.c | base64 
ZyhpLHgsdCxvKXtyZXR1cm4oKDMmeCYoaSooKDMmaT4+MTYgPyAiQll9NllCNiUiIDogIlFqfTZq
UTYlIilbdCU4XSs1MSk+Pm8pKTw8NCk7fTttYWluKGksbixzKXtmb3IoaT0wOztpKyspcHV0Y2hh
cihnKGksMSxuPWk+PjE0LDEyKStnKGkscz1pPj4xNyxuXmk+PjEzLDEwKStnKGkscy8zLG4rKChp
Pj4xMSklMyksMTApK2coaSxzLzUsOCtuLSgoaT4+MTApJTMpLDkpKTt9Cg==

这是不可读的,但是逃脱缩小的C ...