我想在perl中运行shell命令:
var englishTomRNA: [Character: [String]] = ["A": ["UUU", "UAC"],
"Q": ["UUA"],
"S": ["UCU", "UCC", "UCA"]]
var mRNAtoEnglish = [String:Character]()
for (key, value) in englishTomRNA {
for mRNA in value {
mRNAtoEnglish[mRNA] = key
}
}
print(mRNAtoEnglish)
// ["UUU": "A", "UCA": "S", "UCC": "S", "UAC": "A", "UUA": "Q", "UCU": "S"]
但似乎perl无法执行此操作:
tar --exclude="*/node_modules" \
--exclude="*/vendor" \
--exclude='.git' \
-zvcf /tmp/robot.tgz .
这是错误:
`tar --exclude="cv/node_modules" \
--exclude="*/vendor" \
--exclude='.git' \
-zvcf /tmp/robot.tgz .`;
似乎perl将每一行视为一个命令。
答案 0 :(得分:8)
我道歉。我原来的诊断错了
很难在这样的帖子中清楚地表达包含Perl转义字符的字符串的内容。如果您不清楚以下任何内容,请写下评论来说明。我希望我没有让事情变得不必要的复杂化
我在下面的原始解决方案仍然有效,并且可以让您更好地控制命令的内容,但是我为什么OP代码不能为他们工作的原因是错误的,而且事实是真的提供其他决议
问题是反引号(或qx/.../
)的内容被评估为双引号字符串,这意味着Perl变量和转义序列如\t
和在执行字符串之前展开\x20
。其中一个后果是,如果后面跟着一个文字换行符,则会删除反斜杠,只留下换行符
这意味着像这样的声明
my $output = `ls \
-l`;
将被预处理到"ls \n-l"
并且将不再包含向shell发出应该删除换行符所需的反斜杠(或者实际上是首先将命令传递给shell)< / p>
除了我在下面的原始帖子中描述的直接操作命令字符串外,还有两种解决方案。第一个是通过将其加倍来逃避反斜杠本身,就像这个
my $output = `ls \\
-l`;
将阻止它被Perl删除。这会将反斜杠换行序列传递给shell,这将正常删除它
另一种方法是使用qx'...'
而不是反引号和单引号分隔符,这将阻止内容被处理为双引号字符串
my $output = qx'ls \
-l';
除非您在要插补的字符串中使用了Perl变量,否则这将正常工作
问题是shell在执行命令字符串之前删除了前缀为反斜杠的换行符。没有该步骤,命令无效
所以你必须自己在Perl中做同样的事情,为此你必须把命令放在一个临时变量中
use strict;
use warnings 'all';
my $cmd = <<'END';
tar --exclude="*/node_modules" \
--exclude="*/vendor" \
--exclude='.git' \
-zvcf /tmp/robot.tgz .
END
$cmd =~ s/\\\n//g;
my $output = `$cmd`;
当然不需要反斜杠;您可以在执行命令之前简单地使用换行符并删除它们
或者您可能更喜欢将操作包装在子例程中,例如
use strict;
use warnings 'all';
my $output = do_command(<<'END');
tar --exclude="*/node_modules" \
--exclude="*/vendor" \
--exclude='.git' \
-zvcf /tmp/robot.tgz .
END
sub do_command {
my ($cmd) = @_;
$cmd =~ s/\\\n//g;
`$cmd`;
}