RHEL6
我有一个运行perl脚本的c-shell脚本。在将大量的东西转储到stdout之后,它确定perl脚本完成时父shell应当安装到的目录(目录)。但这是一个字符串,而不是一个整数,这就是我可以通过“ exit()”返回的全部。
现在,将dir的名称存储在c-shell脚本可以读取的文件中。它有效,但不优雅。有一个更好的方法吗 ?也许我可以与perl脚本共享一些内存?
短:
重定向Perl的流并最终还原以打印该信息,由shell脚本获取
或者,打印最后的内容,shell脚本可以将输出传递到控制台并获取最后一行
或者,csh对该打印使用命名管道(shell)或特定文件描述符(非)
当Perl脚本打印出该名称时,您可以将其分配给Shell脚本中的变量
#!/bin/csh
set DIR `perl -e'print "dir_name"'`
Run Code Online (Sandbox Code Playgroud)
而在 bash
#!/bin/bash
DIR="$(perl -e'print "dir_name"')"
Run Code Online (Sandbox Code Playgroud)
其中$(...)命令替换的首选位置。
但是随后需要处理从Perl脚本到控制台的其他打印
或者,获取所有Perl的输出并将其传递到控制台,最后一行是所需的“返回”。这使Perl脚本负担最后打印(可能在一个END块中)。程序的输出可以在完成后或逐行输出时从shell脚本中打印出来。
或者,使用Perl脚本可以在其上打印该信息的命名管道(两个外壳程序)或特定文件描述符(bash仅)。在这种情况下,其流直接进入控制台。
该问题明确提到,csh因此在下面给出。但是我必须重复一个古老的事实,那就是shell脚本bash比in 脚本好得多csh。我强烈建议您重新考虑。
如果您需要程序在控制台上的输出,请逐行打印
#!/bin/bash
while read line; do
echo "$line"
DIR=$line
done < <(perl script.pl)
echo "$DIR"
Run Code Online (Sandbox Code Playgroud)
或者,如果脚本完成之前不需要控制台上的输出
#!/bin/bash
mapfile -t lines < <(perl script.pl)
DIR="${lines[-1]}"
printf '%s\n' "${lines[@]}" # print script.pl's output
Run Code Online (Sandbox Code Playgroud)
或者,为该特定打印使用文件描述符
F=$(mktemp) # safe filename
exec 3> "$F" # open fd 3 to write to it
exec 4< "$F" # open fd 4 to read from it
rm -f "$F" # remove file(name) for safety; opened fd's can still access
perl -E'$fd=shift; say "...normal prints to STDOUT...";
open(FH, ">&=$fd") or die $!;
say FH "dirname";
close FH
' 3
read dir_name <&4
exec 3>&- # close them
exec 4<&-
echo "$dir_name"
Run Code Online (Sandbox Code Playgroud)
我无法让它与单个文件描述符同时用于读取和写入(exec 3<> ...),我认为因为写入后读取无法回退,因此使用了单独的描述符。
使用Perl脚本(而不是上面的演示单行代码),将fd号作为命令行选项传递。然后,只有使用该选项调用脚本,脚本才能执行此操作。
或者,使用命名管道与csh下面的操作非常相似。如果STDOUT您不喜欢该程序的操作,那么这可能是最好的选择。
逐行遍历程序的(完成的)输出
#!/bin/csh
foreach line ( "`perl script.pl`" )
echo "$line"
set dir_name = "$line"
end
echo "Directory name: $dir_name"
Run Code Online (Sandbox Code Playgroud)
或先提取最后一行,然后打印整个输出
#!/bin/csh
set lines = ( "`perl script.pl`" )
set dir_name = $lines[$#]
# Print program's output
while ( $#lines )
echo "$lines[1]"
shift lines
end
Run Code Online (Sandbox Code Playgroud)
或使用命名管道
set fifo_name = "/tmp/fifo$$" # or use mktemp
mkfifo "$fifo_name"
( perl script.pl --fifo $fifo_name [other args] & )
set dir_name = `cat "$fifo_name"`
rm -f $fifo_name
echo "dir name from FIFO: $dir_name"
Run Code Online (Sandbox Code Playgroud)
由于FIFO阻塞直到写入和读取,所以Perl命令在后台。因此,如果shell脚本等待perl ...完成,则Perl脚本在写入FIFO时会阻塞(因为未被读取),因此shell将永远无法读取它。我们会陷入僵局。它还在带有的子外壳中,( )以避免出现有关后台作业的信息性打印。
该--fifo NAME命令行选项,需要使Perl脚本知道什么特殊的文件来使用(不这样做,如果该选项不存在)。
对于一个在线示例( perl script ...),也可以用上面也使用过的这种单线替换
( perl -E'$ff = shift; say qq(\t...normal prints to STDOUT...);
open FF, ">$ff" or die $!;
say FF "dir_name_$$";
close FF
' $fifo_name
& )
Run Code Online (Sandbox Code Playgroud)
(为了方便阅读而将行中断)