perl 通过传递到系统的插值将字符串拆分为多行

z5btuh9x  于 8个月前  发布在  Perl
关注(0)|答案(1)|浏览(67)

我正在使用system执行一个命令:

system("keytool -exportcert -rfc -alias  client -file /foo/bar/certificate.pem -keystore  $keystorepath -storepass \$(cat /foo/bar/password ) -v");

这工作,但我希望字符串命令是多行的可读性。
我试

my $cmd = qq {
keytool 
-exportcert 
-rfc -alias  client 
-file /foo/bar/certificate.pem 
-keystore  $keystorepath 
-storepass \$(cat /foo/bar/password ) -v
};
system($cmd);

但我现在收到了错误。错误:

Use "keytool -?, -h, or --help" for this help message
Use "keytool -command_name --help" for usage of command_name.
Use the -conf <url> option to specify a pre-configured options file.
sh: line 1: -exportcert: command not found
sh: line 2: -rfc: command not found
sh: line 3: -alias: command not found
sh: line 4: -file: command not found
sh: line 5: -keystore: command not found
sh: line 6: -storepass: command not found

我做错了什么?

kmynzznz

kmynzznz1#

由于您显然需要在该命令中使用shell,因此需要将其保存在字符串中,†可以通过连接部分来修补命令字符串

my $cmd = join ' ',
    qq( keytool ), 
    qq( -exportcert ), 
    qq( -rfc -alias  client ), 
    qq( -file /foo/bar/certificate.pem ), 
    qq( -keystore  $keystorepath ), 
    qq( -storepass \$(cat /foo/bar/password ) -v );

我在所有字符串上都使用了双引号,但只有一部分需要这样做($keystorepart显然是一个插入命令的Perl变量)。
这样做的一个优点是一致性。另一方面,人们可能只想在需要的地方使用插值,这使得操作更清晰

my $cmd = join ' ',
     q( keytool ), 
     q( -exportcert ), 
     q( -rfc -alias  client ), 
     q( -file /foo/bar/certificate.pem ), 
    qq( -keystore  $keystorepath ), 
     q( -storepass $(cat /foo/bar/password ) -v );

现在我们不转义最后一行中的$,因为它不会被插值,所以它会根据需要被带到shell中。
当然,还有其他方法可以在源代码中组织它。
在问题中所示的尝试中,在该命令中插入了换行符(换行符),这对于shell命令来说是不好的:除非转义,否则换行符会终止命令行,因此shell将使用它在第一个换行符之前的内容运行命令。此外,keytool本身可能无法处理多行调用。
问题更新,现在显示了实际的错误,显示上述两种情况都发生了:firts keytool在没有足够(或任何?)参数的情况下运行(直到第一个换行符?),然后shell将其余的行解释为自己的命令。
†如果不需要shell,最好避免使用shell,一种方法是使用列表形式的system。为此,自然会将上面的命令组件组装在一个数组中,就像它们被列出以连接在一个字符串中一样,然后使用该数组运行system
现在不能这样做,因为shell需要执行嵌入式cat,但是如果你决定将文件放入Perl的变量中,而不是在shell外使用cat,那么考虑一下这个变化。

相关问题