Shell 脚本只接受双引号的第一部分

Shell 脚本只接受双引号的第一部分,shell,perl,environment-variables,double-quotes,Shell,Perl,Environment Variables,Double Quotes,昨天我问了一个类似的问题,关于在env变量中转义双引号,尽管它并没有解决我的问题(可能是因为我解释得不够好),所以我想详细说明一下 我正在尝试运行一个脚本(我知道它是用Perl编写的),但由于权限问题,我不得不将它用作黑盒(所以我不知道脚本是如何工作的)。让我们将此脚本称为script\u A 我正在尝试在Shell中运行一个基本命令:script\u a-arg“date-time”。 如果我从命令行运行,它可以正常工作,但是如果我尝试从bash脚本或perl脚本(例如使用system操作符)

昨天我问了一个类似的问题,关于在env变量中转义双引号,尽管它并没有解决我的问题(可能是因为我解释得不够好),所以我想详细说明一下

我正在尝试运行一个脚本(我知道它是用Perl编写的),但由于权限问题,我不得不将它用作黑盒(所以我不知道脚本是如何工作的)。让我们将此脚本称为
script\u A

我正在尝试在Shell中运行一个基本命令:
script\u a-arg“date-time”
。 如果我从命令行运行,它可以正常工作,但是如果我尝试从bash脚本或perl脚本(例如使用
system
操作符)使用它,它将只接受作为参数发送的字符串的第一部分。换句话说,它将失败并出现以下错误:
““日期”无效。

要指定更多信息的示例:

  • 如果从命令行运行(工作正常):

  • 如果从(例如)Perl脚本运行(失败):

我认为问题来自环境变量,但我不能在定义env变量时使用单引号。例如,我不能使用以下方法:

setenv SOME_ENV '-arg "date time"'
setenv SOME_ENV "-arg '"'date time'"'"
因为它失败并出现以下错误:
““日期”无效。”

此外,我尝试使用以下方法:

setenv SOME_ENV '-arg "date time"'
setenv SOME_ENV "-arg '"'date time'"'"
尽管现在env变量将包含:

echo $SOME_ENV
> -arg 'date time' # should be -arg "date time"
另一个注意事项是,在Shell上使用
\“
失败(尝试过)


关于如何查找错误原因以及如何解决错误的任何建议?

如图所示,从
%ENV
获取的
$args
是一个字符串

问题在于在将参数传递给程序之前对该字符串进行操作时会发生什么情况,程序需要接收字符串
-arg
日期时间

  • 如果程序以绕过shell的方式执行,如您的示例所示,那么整个
    -arg“date-time”
    将作为其第一个参数传递给它。这显然是错误的,因为程序需要
    -arg
    ,然后需要另一个字符串作为其值(
    日期时间

  • 如果程序是通过shell执行的,那么当命令行中有shell元字符时会发生什么情况(在您的示例中不是这样),那么shell会将字符串分解为单词,除了带引号的部分;这就是它在命令行中的工作方式。这可以通过

    system('/bin/tcsh', '-c', $cmd);
    
    这是最简单的修复方法,但我不能诚实地建议仅将shell用于参数解析。同时,你也在玩分层引用和逃避的游戏,这会让你变得相当复杂和棘手。首先,如果事情不对,shell可能会将命令分解为单词
    -arg
    “date
    time”

设置环境变量的工作方式

> setenv SOME_ENV '-arg "date time"'   

> perl -wE'say $ENV{SOME_ENV}'  #--> -arg "date time"  (so it works)
我所相信的在csh中一直是这样运作的

然后,在Perl脚本中:将该字符串解析为
-arg
日期时间
字符串,并以绕过shell的方式执行程序(如果命令未使用shell)

这假设
SOME_ENV
的第一个单词始终是选项的名称(
-arg
),其余的单词始终是选项的值,并在引号下。正则表达式提取第一个单词,作为连续的非空格字符,并在引号中的所有单词后面加空格。†这些是程序的参数

系统列表
表单中,作为列表第一个元素的程序在不使用shell的情况下执行,其余元素作为参数传递给它。有关这方面的更多信息,以及如何通过调查来调查失败的基础知识,请参见

原则上,建议在不使用shell的情况下运行外部命令。但是,如果您的命令需要shell,那么请确保转义字符串正好可以保留引号

请注意,有一些模块使使用外部命令更容易。一些,从简单到复杂:、和

我必须指出,这是一个令人尴尬的环境变量;有没有别的办法可以把事情搞糟


†要使此操作也适用于非引用参数(
-arg date
),请将引用设置为可选

my @args = $ENV{SOME_ENV} =~ /(\S+)\s+"?([^"]+)/;

为了简单起见,我现在省略了结束语(不必要的)引号

您使用的是什么系统,什么版本?这是
tcsh
,对吗?在
tcsh
(tcshell)下,使用您显示的第一种方式设置确切的环境变量对我很有效,我认为它一直都是这样工作的(对于该shell)。感谢您的重播。有没有可能像在perl中那样通过tchl解决这个问题?@TTaJTa4如果您将在命令行上运行的内容放入shell脚本中,它应该可以正常工作(这就是您要问的吗?)。另外,请参见答案中的编辑。
my @args = $ENV{SOME_ENV} =~ /(\S+)\s+"?([^"]+)/;