脚本只需要双引号的第一部分
Script takes only first part of double quotes
昨天我问了一个关于在环境变量中转义双引号的类似问题,虽然它没有解决我的问题(可能是因为我解释得不够好)所以我想详细说明。
我正在尝试 运行 一个脚本(我知道它是用 Perl 编写的),尽管由于权限问题我不得不将它用作黑盒(所以我不知道如何脚本有效)。让我们调用此脚本 script_A
.
我正在尝试 运行 Shell 中的基本命令:script_A -arg "date time"
。
如果我从命令行 运行,它工作正常,但如果我尝试从 bash 脚本或 perl 脚本(例如使用 system
运算符)使用它,它将需要只有作为参数发送的字符串的第一部分。换句话说,它将失败并出现以下错误:'"date' is not valid.
.
具体说明的示例:
如果我从命令行运行(工作正常):
> script_A -arg "date time"
如果我 运行 来自(例如)Perl 脚本(失败):
my $args = $ENV{SOME_ENV}; # Assume that SOME_ENV has '-arg "date time"'
my $cmd = "script_A $args";
system($cmd");
我认为问题出在环境变量上,但我在定义环境变量时不能使用单引号。比如我不能用下面的方法:
setenv SOME_ENV '-arg "date time"'
因为它失败并出现以下错误:'"date' is not valid."
.
此外,我尝试使用以下方法:
setenv SOME_ENV "-arg '"'date time'"'"
尽管现在环境变量将包含:
echo $SOME_ENV
> -arg 'date time' # should be -arg "date time"
另一个注意事项,使用 \"
在 Shell 上失败(试过了)。
关于如何定位错误原因和解决方法有什么建议吗?
如您所示,从 %ENV
获得的 $args
是一个字符串。
问题在于,在将参数传递给需要接收字符串 -arg
和 date time
的程序之前,该字符串会发生什么情况?
如果程序以绕过 shell 的方式执行,如您的示例所示,那么整个 -arg "date time"
将作为第一个参数传递给它。这显然是错误的,因为程序需要 -arg
然后是另一个字符串作为它的值 (date time
)
如果程序是通过 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)
我相信在 [t]csh
中一直以这种方式起作用。
然后,在 Perl 脚本中:将此字符串解析为 -arg
和 date time
字符串,并以绕过 shell 的方式执行程序(如果 shell 未被命令使用)
my @args = $ENV{SOME_ENV} =~ /(\S+)\s+"([^"]+)"/; #"
my @cmd = ('script_A', @args);
system(@cmd) == 0 or die "Error with system(@cmd): $?";
这假定 SOME_ENV
的第一个词始终是选项的名称 (-arg
),并且所有其余部分始终是选项的值,在引号下。正则表达式提取第一个单词,作为连续的非 space 字符,在 space 之后的所有内容都用引号引起来。† 这些是程序的参数。
在 system LIST
形式中,作为列表第一个元素的程序在不使用 shell 的情况下执行,其余元素作为参数传递给它。请参阅 system for more on this, and also for basics of how to investigate failure by looking into $?
variable。
原则上建议 运行 没有 shell 的外部命令。但是,如果您的命令 需要 和 shell,那么请确保将字符串正确转义以保留引号。
请注意,有些模块可以更轻松地使用外部命令。几个,从简单到复杂:IPC::System::Simple, Capture::Tiny, IPC::Run3, and IPC::Run.
我必须指出,这是一个尴尬的环境变量;有什么方法可以将事物组织化吗?
† 要使此功能也适用于非引号参数 (-arg date
),请将引号设为可选
my @args = $ENV{SOME_ENV} =~ /(\S+)\s+"?([^"]+)/;
为了简单起见,我现在省略了结束语(不必要的)
昨天我问了一个关于在环境变量中转义双引号的类似问题,虽然它没有解决我的问题(可能是因为我解释得不够好)所以我想详细说明。
我正在尝试 运行 一个脚本(我知道它是用 Perl 编写的),尽管由于权限问题我不得不将它用作黑盒(所以我不知道如何脚本有效)。让我们调用此脚本 script_A
.
我正在尝试 运行 Shell 中的基本命令:script_A -arg "date time"
。
如果我从命令行 运行,它工作正常,但如果我尝试从 bash 脚本或 perl 脚本(例如使用 system
运算符)使用它,它将需要只有作为参数发送的字符串的第一部分。换句话说,它将失败并出现以下错误:'"date' is not valid.
.
具体说明的示例:
如果我从命令行运行(工作正常):
> script_A -arg "date time"
如果我 运行 来自(例如)Perl 脚本(失败):
my $args = $ENV{SOME_ENV}; # Assume that SOME_ENV has '-arg "date time"' my $cmd = "script_A $args"; system($cmd");
我认为问题出在环境变量上,但我在定义环境变量时不能使用单引号。比如我不能用下面的方法:
setenv SOME_ENV '-arg "date time"'
因为它失败并出现以下错误:'"date' is not valid."
.
此外,我尝试使用以下方法:
setenv SOME_ENV "-arg '"'date time'"'"
尽管现在环境变量将包含:
echo $SOME_ENV
> -arg 'date time' # should be -arg "date time"
另一个注意事项,使用 \"
在 Shell 上失败(试过了)。
关于如何定位错误原因和解决方法有什么建议吗?
如您所示,从 %ENV
获得的 $args
是一个字符串。
问题在于,在将参数传递给需要接收字符串 -arg
和 date time
如果程序以绕过 shell 的方式执行,如您的示例所示,那么整个
-arg "date time"
将作为第一个参数传递给它。这显然是错误的,因为程序需要-arg
然后是另一个字符串作为它的值 (date time
)如果程序是通过 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)
我相信在 [t]csh
中一直以这种方式起作用。
然后,在 Perl 脚本中:将此字符串解析为 -arg
和 date time
字符串,并以绕过 shell 的方式执行程序(如果 shell 未被命令使用)
my @args = $ENV{SOME_ENV} =~ /(\S+)\s+"([^"]+)"/; #"
my @cmd = ('script_A', @args);
system(@cmd) == 0 or die "Error with system(@cmd): $?";
这假定 SOME_ENV
的第一个词始终是选项的名称 (-arg
),并且所有其余部分始终是选项的值,在引号下。正则表达式提取第一个单词,作为连续的非 space 字符,在 space 之后的所有内容都用引号引起来。† 这些是程序的参数。
在 system LIST
形式中,作为列表第一个元素的程序在不使用 shell 的情况下执行,其余元素作为参数传递给它。请参阅 system for more on this, and also for basics of how to investigate failure by looking into $?
variable。
原则上建议 运行 没有 shell 的外部命令。但是,如果您的命令 需要 和 shell,那么请确保将字符串正确转义以保留引号。
请注意,有些模块可以更轻松地使用外部命令。几个,从简单到复杂:IPC::System::Simple, Capture::Tiny, IPC::Run3, and IPC::Run.
我必须指出,这是一个尴尬的环境变量;有什么方法可以将事物组织化吗?
† 要使此功能也适用于非引号参数 (-arg date
),请将引号设为可选
my @args = $ENV{SOME_ENV} =~ /(\S+)\s+"?([^"]+)/;
为了简单起见,我现在省略了结束语(不必要的)