如何将参数传递给expect -c脚本?

huangapple go评论90阅读模式
英文:

how to pass arguments to expect -c script?

问题

抱歉,我不能执行代码。如果你有关于代码的问题或需要帮助,我可以提供一般性的建议和指导。

英文:

I want to run a temporary expect script with arguments and leave stdin open:

expect -c 'spawn {*}$argv' /dev/null echo hello world

However this results in

can't read "argv": no such variable
    while executing
"spawn {*}$argv"

How do I execute it?

答案1

得分: 1

请查看args解析的源代码

 656 void
 657 exp_parse_argv(interp, argc, argv)
 658 Tcl_Interp *interp;
 659 int argc;
 660 char **argv;
 661 {
 ...

 703     while ((c = getopt(argc, argv, "+b:c:dD:f:inN-v")) != EOF) {
 704         switch(c) {
 ...

 711         case 'c': /* command */
 712             exp_cmdlinecmds = TRUE;
 713             rc = Tcl_Eval(interp, optarg);
 714             if (rc != TCL_OK) {
 715                 expErrorLogU(exp_cook(Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY), (int *)0));
 716                 expErrorLogU("\r\n");
 717             }
 718             break;
 ...

 773     }
 ...

 850     /* 收集剩余的参数并形成 argc、argv0 和 argv */
 851     sprintf(argc_rep, "%d", argc - optind);
 852     Tcl_SetVar(interp, "argc", argc_rep, 0);
 853     expDiagLog("set argc %s\r\n", argc_rep);
 854
 855     if (exp_cmdfilename) {
 856         Tcl_SetVar(interp, "argv0", exp_cmdfilename, 0);
 857         expDiagLog("set argv0 \"%s\"\r\n", exp_cmdfilename);
 858     } else {
 859         Tcl_SetVar(interp, "argv0", exp_argv0, 0);
 860         expDiagLog("set argv0 \"%s\"\r\n", exp_argv0);
 861     }
 862
 863     args = Tcl_Merge(argc - optind, argv + optind);
 864     expDiagLogU("set argv \"");
 865     expDiagLogU(args);
 866     expDiagLogU("\"\r\n");
 867     Tcl_SetVar(interp, "argv", args, 0);
 868     Tcl_Free(args);
 869
 870     exp_interpret_rcfiles(interp, my_rc, sys_rc);
 871 }

它按照以下顺序运行:

  • while 循环的第703行,使用 -c command(第711行)通过 Tcl_Eval()(第713行)运行。
  • 第852行设置了 Tcl 的变量 argc
  • 第856/859行设置了 argv0
  • 第867行设置了 argv

因此,当运行 -c command 时,argv0/argc/argv 还不可用。


这也可以通过 expect -d 显示:

$ expect -d -c 'puts "now in -c command" ' /dev/null foo bar
expect 版本 5.45
now in -c command                  <====
argv[0] = expect  argv[1] = -d  argv[2] = -c  argv[3] = puts "now in -c command"
argv[4] = /dev/null  argv[5] = foo  argv[6] = bar
set argc 2                         <====
set argv0 "/dev/null"              <====
set argv "foo bar"                 <====
正在执行来自命令文件 /dev/null 的命令
英文:

See the source code for args parsing:

 656 void
 657 exp_parse_argv(interp,argc,argv)
 658 Tcl_Interp *interp;
 659 int argc;
 660 char **argv;
 661 {
 ...

 703     while ((c = getopt(argc, argv, "+b:c:dD:f:inN-v")) != EOF) {
 704         switch(c) {
 ...

 711         case 'c': /* command */
 712             exp_cmdlinecmds = TRUE;
 713             rc = Tcl_Eval(interp,optarg);
 714             if (rc != TCL_OK) {
 715                 expErrorLogU(exp_cook(Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY),(int *)0));
 716                 expErrorLogU("\r\n");
 717             }
 718             break;
 ...

 773     }
 ...

 850     /* collect remaining args and make into argc, argv0, and argv */
 851     sprintf(argc_rep,"%d",argc-optind);
 852     Tcl_SetVar(interp,"argc",argc_rep,0);
 853     expDiagLog("set argc %s\r\n",argc_rep);
 854
 855     if (exp_cmdfilename) {
 856         Tcl_SetVar(interp,"argv0",exp_cmdfilename,0);
 857         expDiagLog("set argv0 \"%s\"\r\n",exp_cmdfilename);
 858     } else {
 859         Tcl_SetVar(interp,"argv0",exp_argv0,0);
 860         expDiagLog("set argv0 \"%s\"\r\n",exp_argv0);
 861     }
 862
 863     args = Tcl_Merge(argc-optind,argv+optind);
 864     expDiagLogU("set argv \"");
 865     expDiagLogU(args);
 866     expDiagLogU("\"\r\n");
 867     Tcl_SetVar(interp,"argv",args,0);
 868     Tcl_Free(args);
 869
 870     exp_interpret_rcfiles(interp,my_rc,sys_rc);
 871 }

It runs in this order:

  • Line 703, in the while loop, -c command (line 711) is run with Tcl_Eval() (line 713).
  • Line 852 sets Tcl's var argc.
  • Line 856/859 sets argv0.
  • Line 867 sets argv.

So when -c command is run, argv0/argc/argv are not yet available.


This can also be shown with expect -d:

$ expect -d -c 'puts "now in -c command" ' /dev/null foo bar
expect version 5.45
now in -c command                  <====
argv[0] = expect  argv[1] = -d  argv[2] = -c  argv[3] = puts "now in -c command"
argv[4] = /dev/null  argv[5] = foo  argv[6] = bar
set argc 2                         <====
set argv0 "/dev/null"              <====
set argv "foo bar"                 <====
executing commands from command file /dev/null

huangapple
  • 本文由 发表于 2023年8月10日 15:44:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76873592.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定