use*_*209 4 scripting bash perl shell-script
我有一个包含两个块的脚本:第一个块是用 perl 编写的,第二个块是用 bash 编写的
如何在脚本中间切换 shell(perl --> bash)?下面附上脚本:
#! /usr/bin/perl -w
#
my @dirs = glob("*.frames");
foreach $dir (@dirs) {
print "working on $dir\n";
chdir $dir;
my @digitfiles = glob ("RawImage_?.tif"); #need to make all files have 2-digit numbering for sort order to be correct
foreach $file (@digitfiles) {
my $newfile = $file;
$newfile =~ s/RawImage_/RawImage_0/;
rename $file,$newfile;
}
my $stackname = "../" . $dir . ".mrc";
`tif2mrc -s *.tif $stackname`; #IMOD program to stack: -s option means treat input as signed INT
chdir "../"; #go back up
}
#!/usr/bin/env bash
for f in *.mrc; do mv -- "$f" "${f%%.*}".mrc ; done
Run Code Online (Sandbox Code Playgroud)
cho*_*oba 27
只需在 Perl 中重写循环:
for my $file (glob '*.mrc') {
( my $newname = $file ) =~ s/\..*/.mrc/;
rename $file, $newname or warn "$file: $!";
}
Run Code Online (Sandbox Code Playgroud)
Sté*_*las 19
忽略XY 问题并回答主题中的问题,您可以执行以下操作:
#! /usr/bin/perl
":" || q@<<"=END_OF_PERL"@;
# perl code here
exec "bash", "--", $0, @ARGV;
=END_OF_PERL@
# bash code here
Run Code Online (Sandbox Code Playgroud)
bash
将忽略该部分直到该=END_OF_PERL@
行,因为它是:
: || something <<"=END_OF_PERL@"
...
=END_OF_PERL@
Run Code Online (Sandbox Code Playgroud)
而第一行,在 perl 中只是两个字符串(":"
和q@quoted-string@
)ORed在一起,所以没有操作。
=END_OF_PERL@
inperl
是pod
(文档)部分的开头,因此被perl
.
请注意,如果你想从传递变量perl
来bash
,你必须将它们导出到环境(虽然你也可以使用参数;在这里,我们要转发的参数的列表perl
收到脚本bash
脚本):
$ENV{ENV_VAR} = $perl_var;
Run Code Online (Sandbox Code Playgroud)
代码假定该perl
部分不会更改当前工作目录,否则如果$0
是相对路径,则传递给bash
. 要解决这个问题,您可以在开始时使用脚本的绝对路径:
#! /usr/bin/perl
":" || q@<<"=END_OF_PERL"@;
use Cwd "fast_abs_path";
my $script_path = fast_abs_path $0;
# perl code here
exec "bash", "--", $script_path, @ARGV;
=END_OF_PERL@
# bash code here
Run Code Online (Sandbox Code Playgroud)
这是多语言脚本的一个示例,该脚本是一种以上语言的有效代码。如果您喜欢这些技巧,可以在这里查看更极端的技巧或codegolf Q&A。
perldoc perlrun
显示了sh
+perl
多语言的另一个示例,但这次sh
首先被调用(对于不支持 she-bangs 的系统)。
你不能切换解释器,但你可以产生一个新的 shell 进程,然后返回到 perl:
my $sh_code = <<'END_SH'
for f in *.mrc; do mv -- "$f" "${f%%.*}".mrc ; done
END_SH
system 'bash', '-c', $sh_code
Run Code Online (Sandbox Code Playgroud)
或者你可以用一个 shell 替换当前的 perl 进程
exec 'bash', '-c', $sh_code
Run Code Online (Sandbox Code Playgroud)
但正如@choroba 所回答的那样,perl 是一种通用语言,几乎可以处理任何任务。