我应该在Perl中转义shell参数吗?

我应该在Perl中转义shell参数吗?,perl,shell,arguments,Perl,Shell,Arguments,在Perl中使用调用时,是必须转义shell参数,还是自动转义 参数将是用户输入,因此我想确保这是不可利用的。如果使用system$cmd、@args而不是system“$cmd@args”(数组而不是字符串),则不必转义参数,因为没有调用shell(请参阅)system{$cmd}$cmd,@args也不会调用shell,即使$cmd包含元字符且@args为空(这是作为的一部分记录的)。如果参数来自用户输入(或其他不受信任的源),您仍然需要将其卸载。参见文档中的-T,以及文档 如果需要读取输出

在Perl中使用调用时,是必须转义shell参数,还是自动转义


参数将是用户输入,因此我想确保这是不可利用的。

如果使用
system$cmd、@args
而不是
system“$cmd@args”
(数组而不是字符串),则不必转义参数,因为没有调用shell(请参阅)
system{$cmd}$cmd,@args
也不会调用shell,即使$cmd包含元字符且@args为空(这是作为的一部分记录的)。如果参数来自用户输入(或其他不受信任的源),您仍然需要将其卸载。参见文档中的
-T
,以及文档


如果需要读取输出或向命令发送输入,
qx
readpipe
没有等效项。相反,可以使用
打开我的$output,“-”、$cmd、@args
打开我的$input,“-”、$cmd、@args
,尽管这是不可移植的,因为它需要真正的
fork
,这意味着只使用Unix。。。我想。也许它可以在Windows上使用模拟的叉子。一个更好的选项是这样的,它还将处理管道命令到其他命令的情况,而系统的多参数形式和open的4参数形式都无法处理这种情况。

在Windows上,情况有点糟糕。基本上,所有Win32程序都接收一个长的命令行字符串——shell(通常是
cmd.exe
)可以先进行一些解释,例如删除
重定向,但它不会在程序的字边界处将其拆分。每个程序都必须自己进行解析(如果他们愿意的话——有些程序不需要)。在C和C++程序中,由编译器工具链提供的运行库提供的例程通常在“代码>主())< /C> >之前执行此解析步骤。 问题是,一般来说,您不知道给定程序将如何解析其命令行。许多程序是用MSVC++的某些版本编译的,而其他许多程序是用使用不同约定的不同编译器编译的

这一点由于
cmd.exe
有其独特的解析规则而变得更加复杂。插入符号(
^
)被视为一个转义字符,它引用以下字符,如果满足一系列棘手的条件,则双引号内的文本被视为被引用(有关详细信息,请参见
cmd/?
)。如果您的命令包含任何奇怪的字符,
cmd.exe
很容易就知道哪些部分的文本是“引用”的,哪些部分不会与目标程序的不同步,所有的麻烦都会迎刃而解

因此,在Windows上转义参数的最安全方法是:

  • 以所调用程序的命令行解析逻辑所期望的方式转义参数。(希望您知道这种逻辑是什么;如果不知道,请尝试几个示例并猜测。)
  • 用空格连接转义参数
  • 在结果字符串的每个非字母数字字符前面加上
    ^
  • 附加任何重定向或其他shell欺骗(例如,使用
    &&
    连接命令)
  • 使用
    system()
    或反勾号运行命令

  • 你问题的答案很有用。最后,我听从了@runrig的建议,但随后使用了核心模块open3()命令,以便从STDERR和STDOUT中捕获输出

    有关与@runrig的解决方案一起使用的open3()示例代码,请参阅我的相关问题和答案:

    子esc\u字符{
    #将更改,例如,a!!a更改为a\!\!a
    @_=~s/([;\*\\\\\`&\$!\\\(\)\[\]\{\}:'“])/\$1/g;
    返回,;
    }
    

    如果使用系统“$cmd@args”(字符串),则必须转义参数,因为调用了shell

    幸运的是,对于双引号字符串,只需要转义四个字符:

    "    - double quote
    $    - dollar
    @    - at symbol
    \    - backslash
    

    转义shell args是什么意思?是指在“>”或“”等字符前面加上“?”,还是要包含转义$,这样人们就不能插入Perl变量?还是什么?请举例说明您的意思。如何在系统调用中添加大括号….System(“$jboss\u client/subsystem=logging/size rotating file handler=SAMPLE:add\(formatter={yyyy\});我总是像下面这样得到结果……formatter=yyyy instaed of farmatter={yyyyy}。你能给我一个解决这个问题的方法吗?作为补充,
    system{cmd“cmd”
    总是绕过
    sh
    ,即使
    'cmd'
    包含通常由shell解释的字符。您应该补充一点,不必使用“system'cmd'@args”转义shell元字符的原因是在这种情况下没有调用shell(因为OP询问shell元字符是否会“自动”转义,事实并非如此)。+1,我很混乱——我以前从未听说过间接对象语法!我一直在测试“系统”和“打开我的$output”"解决方案,但也不允许我将STDERR重定向到一个文件,这很遗憾意味着我不能在我的场景中使用该解决方案。我假设该解决方案按设计工作,但希望在信息帮助他人的情况下共享。@schulwitz-他想将STDERR重定向到一个文件,试试看,它很管用。有趣的信息-谢谢。它不会使Windows受到这个美国用户的喜爱尼克松主义者,但这有助于了解幕后发生了什么。(参考页对插入符号的作用有点沉默!它提到了插入符号,但只是例外。例如,它如何处理^ \或^“,并不清楚。)我同意乔纳森·莱夫勒的观点。也就是说(在我看来)处理命令行争论的糟糕方法。我完全同意这是一种糟糕的情况。虽然公平地说,大多数令人不快的地方可能来自于MS对保持向后兼容性的值得称赞的投入。(要了解他们有多着迷,请查看Raymond Chen的优秀博客。)
    "    - double quote
    $    - dollar
    @    - at symbol
    \    - backslash