RHEL6
我有一个运行perl脚本的c-shell脚本。在将大量内容转储到stdout之后,它确定了当perl脚本完成时父shell应该cd到哪里(什么dir)。但这是一个字符串,而不是一个int,这是我可以用“exit()”传回来的。
将dir的名称存储在c-shell脚本可以读取的文件中,这就是我现在所拥有的。它有效,但不优雅。有一个更好的方法吗 ?也许我可以用perl脚本分享一小块内存?
答案 0 :(得分:4)
简短:
重定向Perl的流并在最后恢复以打印由shell脚本获取的信息
或者,打印 last 并且shell脚本可以将输出传递给控制台并采取最后一行
或者,对该打印使用命名管道(shell)或特定文件描述符(不是csh
)
当Perl脚本打印出该名称时,您可以将其分配给变量 在shell脚本中
#!/bin/csh
set DIR `perl -e'print "dir_name"'`
在bash
中的
#!/bin/bash
DIR="$(perl -e'print "dir_name"')"
其中$(...)
是命令替换的首选。
但是需要处理从Perl脚本到控制台的其他打印件
或者,取所有Perl的输出并将其传递给控制台,最后一行是所需的“返回”。这使得Perl脚本的负担最后打印(可能在END
块中)。程序的输出可以在shell脚本完成后打印,也可以在发出时逐行打印。
或者,使用命名管道(两个shell)或特定文件描述符(仅bash
),Perl脚本可以将该信息打印到该文件。在这种情况下,它的流直接进入控制台。
问题明确提到csh
所以它在下面给出。但是我必须重复一个陈旧的事实,即bash
中的shell脚本编写要比csh
好得多。我强烈建议重新考虑。
如果您需要控制台上的程序输出,请逐行拍摄并打印
#!/bin/bash
while read line; do
echo "$line"
DIR=$line
done < <(perl script.pl)
echo "$DIR"
或者,如果在脚本完成之前不需要在控制台上输出
#!/bin/bash
mapfile -t lines < <(perl script.pl)
DIR="${lines[-1]}"
printf '%s\n' "${lines[@]}" # print script.pl's output
或者,使用特定打印的文件描述符
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"
我无法使用单个文件描述符来读取和写入(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"
或先提取最后一行,然后打印整个输出
#!/bin/csh
set lines = ( "`perl script.pl`" )
set dir_name = $lines[$#]
# Print program's output
while ( $#lines )
echo "$lines[1]"
shift lines
end
或使用命名管道
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"
Perl命令在后台处于FIFO状态,直到写入和读取为止。因此,如果shell脚本要等待perl ...
完成,那么Perl脚本会在写入FIFO时阻塞(因为它没有被读取)所以shell永远不会读取它;我们会陷入僵局。它也在子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
& )
(为了便于阅读而划清界限)