注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Tsecer的回音岛

Tsecer的博客

 
 
 

日志

 
 

bash中命令及变量展开顺序  

2013-07-11 23:54:03|  分类: bash分析 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、循环中中的变量集合展开
对于循环命令,通常我们需要有一个变量的集合,然后对这些内容进行迭代。但是有时又我们需要知道这个命令执行和变量展开的精确时间顺序。举个例子说,我们有这样一个命令
for file in  file*
do
some command  $file > $file.log 2>&1
done
这个地方大家注意一下,在循环体中的$file.log是同样满足for循环中的匹配条件的,那么此时命令生成的log文件会被for再次读入吗?
二、对于for文件的展开
static int
execute_for_command (for_command)
     FOR_COM *for_command;

  identifier = for_command->name->word;

  list = releaser = expand_words_no_vars (for_command->map_list);
……
……
  for (retval = EXECUTION_SUCCESS; list; list = list->next)
    {
      QUIT;

      line_number = for_command->line;

      /* Remember what this command looks like, for debugger. */
      command_string_index = 0;
      print_for_command_head (for_command);

      if (echo_command_at_execute)
    xtrace_print_for_command_head (for_command);

      /* Save this command unless it's a trap command and we're not running
     a debug trap. */
#if 0
      if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
#else
      if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
#endif
    {
      FREE (the_printed_command_except_trap);
      the_printed_command_except_trap = savestring (the_printed_command);
    }

      retval = run_debug_trap ();
#if defined (DEBUGGER)
      /* In debugging mode, if the DEBUG trap returns a non-zero status, we
     skip the command. */
      if (debugging_mode && retval != EXECUTION_SUCCESS)
        continue;
#endif

      this_command_name = (char *)NULL;
      v = bind_variable (identifier, list->word->word, 0);
      if (readonly_p (v) || noassign_p (v))
    {
      line_number = save_line_number;
      if (readonly_p (v) && interactive_shell == 0 && posixly_correct)
        {
          last_command_exit_value = EXECUTION_FAILURE;
          jump_to_top_level (FORCE_EOF);
        }
      else
        {
          dispose_words (releaser);
          discard_unwind_frame ("for");
          loop_level--;
          return (EXECUTION_FAILURE);
        }
    }
      retval = execute_command (for_command->action);
      REAP ();
      QUIT;

      if (breaking)
    {
      breaking--;
      break;
    }

      if (continuing)
    {
      continuing--;
      if (continuing)
        break;
    }
    }
大家可以看到,在for循环之前,已经通过expand_words_no_vars (for_command->map_list)将for 文件的参数首先进行了变量的展开,而文件的匹配此时也是变量展开的一种形式,所以动态生成的文件是不会被作为循环变量。
三、变量展开的定界
expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)

  for (sindex = 0; ;)
    {
      c = string[sindex];

      /* Case on toplevel character. */
      switch (c)
    {
……
case '$':
      if (expanded_something)
        *expanded_something = 1;

      has_dollar_at = 0;
      pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0;
      if (word->flags & W_NOSPLIT2)
        pflags |= PF_NOSPLIT2;
      tword = param_expand (string, &sindex, quoted, expanded_something,
                   &has_dollar_at, &quoted_dollar_at,
                   &had_quoted_null, pflags);

     ……
      break;

static WORD_DESC *
param_expand (string, sindex, quoted, expanded_something,
          contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
          pflags)

  /* Do simple cases first. Switch on what follows '$'. */
  switch (c)
    {
    /* $0 .. $9? */
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      temp1 = dollar_vars[TODIGIT (c)];
      if (unbound_vars_is_error && temp1 == (char *)NULL)
    {
      uerror[0] = '$';
      uerror[1] = c;
      uerror[2] = '\0';
      last_command_exit_value = EXECUTION_FAILURE;
      err_unboundvar (uerror);
      return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
    }
      if (temp1)
    temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
          ? quote_string (temp1)
          : quote_escapes (temp1);
      else
    temp = (char *)NULL;

      break;
……
   default:
      /* Find the variable in VARIABLE_LIST. */
      temp = (char *)NULL;

      for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
    ;
      temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;

      /* If this isn't a variable name, then just output the `$'. */
      if (temp1 == 0 || *temp1 == '\0')
    {
      FREE (temp1);
      temp = (char *)xmalloc (2);
      temp[0] = '$';
      temp[1] = '\0';
      if (expanded_something)
        *expanded_something = 0;
      goto return0;
    }

      /* If the variable exists, return its value cell. */
      var = find_variable (temp1);

#define legal_variable_char(c)    (ISALNUM(c) || c == '_')
‘$’后面中跟的哪些字符是变量名呢?bash的变量定义词法规则和C语言相同的。那么此时 0var 是不是整个都是一个整体的变量名呢?在上下文看看就知道不是了,因为‘$’后面的0在之前的switch中的数字分支中处理,所以轮不到这里来处理。同理,对于$$,$?之类形式的变量也是在其他的case中处理的,而default的则是其他的一些不符合之前case分支的条件满足。
  评论这张
 
阅读(711)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017