bash命令行处理流程及关于双引号的源码解析

之前在执行脚本时发现一个问题:

cat a.sh
#!/bin/bash
OPTS="--conf javaOption=\"-Da=b -Dc=d\""
eval ./c.sh $OPTS
./c.sh $OPTS
cat c.sh
#!/bin/bash
n=$#
for ((i=0; i<n; i++));do
        echo "$i:{"$1"}"
        shift
done

对于加eval和不加eval处理的./c.sh $OPTS命令结果是不一样的,而且直接的./c.sh $OPTS得出的并不是我们想要的结果:
一、eval ./c.sh $OPTS
结果:
0:{–conf}
1:{javaOption=-Da=b -Dc=d}
二、./c.sh $OPTS
结果:
0:{–conf}
1:{javaOption=”-Da=b}
2:{-Dc=d”}
为了说明这个问题,我们分为两步:
(1)说明bash命令行处理流程;
(2)使用grep命令+log打印+gdb+xcode来从源码里解释流程。

首先来说一下bash命令行处理流程,分为12步,来自《学习bash》这本书中,流程图如下:
这里写图片描述
下边来举个例子,这是我在下载的bash源码中添加了printf输出后的一个简单命令执行的输出:
$ cat test1.sh
./c.sh –conf javaOption=”-Da=b -Dc=d”
$ ../bash-4.4/bash test1.sh
reader_loop
read_command
parse_command
yyparse
Starting parse
[Function]read_token
reserved_word_acceptable
CHECK_FOR_RESERVED_WORD
reserved_word_acceptable
reserved_word_acceptable
[Function]read_token
reserved_word_acceptable
CHECK_FOR_RESERVED_WORD
reserved_word_acceptable
reserved_word_acceptable
[Function]read_token
reserved_word_acceptable
CHECK_FOR_RESERVED_WORD
reserved_word_acceptable
reserved_word_acceptable
[Function]read_token
expand_words
brace_expansion //大括号扩展
shell_expand_word_list //5-8步
string_extract_double_quoted //双引号处理
-Da=b -Dc=d
dequote_string
-Da=b -Dc=d
quote_string
dequote_string
dequote_string
dequote_string
0:{–conf}
1:{javaOption=-Da=b -Dc=d}

上边的输出基本对应12步处理流程,下边来具体分析:

脚本内容:
OPTS=”–conf javaOption=\”-Da=b -Dc=d\””
./c.sh $OPTS
执行结果如下:
0:{–conf}
1:{javaOption=”-Da=b}
2:{-Dc=d”}

脚本内容:
./c.sh –conf javaOption=”-Da=b -Dc=d”
执行结果如下:
0:{–conf}
1:{javaOption=-Da=b -Dc=d}
这里第一个脚本未对双引号进行处理,为什么呢?
出现这种不同,主要是在于命令行处理流程中对于双引号的处理位置。在命令行处理流程中,位于subst.c文件9017(大约位置,因为加log信息后有变)处的函数 expand_word_internal()是处理从第五步波浪号扩展到第八步算术替换的核心函数,而实际对于双引号的处理是在与这几步变换并列的一个switch语句里,bash在处理完 switchswitchcase 符号的相关扩展在前,双引号处理的在后。
在subst.c中添加的log信息如下:
这里写图片描述

这里写图片描述

这里写图片描述

对于./c.sh $OPTS的执行过程中打印:
[DEBUG] word: ./c.sh
[DEBUG] word: $OPTS
[DEBUG]$ begin substitute //在这里执行$OPTS的参数扩展
[DEBUG]$ end substitute
之后直接跳出switch循环了。

而对于./c.sh –conf javaOption=”-Da=b -Dc=d”的执行过程中打印:
[DEBUG] word: ./task/c.sh
[DEBUG] word: –conf
[DEBUG] word: javaOption=”-Da=b -Dc=d”
[DEBUG]double_quote processing //处理双引号
[DEBUG] word: -Da=b -Dc=d
Detaching after fork from child process 14855.
0:{–conf}
1:{javaOption=-Da=b -Dc=d}
在接下来的switch里边会处理到双引号,调用string_extract_double_quoted()函数将引号内字符串处理为一个整体。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值