bugfix> perl > 投稿

RHEL6

perlスクリプトを実行するc-shellスクリプトがあります。大量のものをstdoutにダンプした後、perlスクリプトの終了時に親シェルがどこ(どのディレクトリ)に移動するかを決定します。しかし、それは文字列であり、「exit()」で戻すことができるintではありません。

ディレクトリの名前をc-shellスクリプトが読み取れるファイルに保存することは、私が今持っているものです。動作しますが、エレガントではありません。これを行うより良い方法はありますか?たぶん、perlスクリプトと共有できるメモリの小さな塊ですか?

回答 1 件
  • ショート:  

    Perlのストリームをリダイレクトし、最後に復元して、シェルスクリプトによって取得された情報を出力します

    または、それを印刷する最終 シェルスクリプトはコンソールに出力を渡し、最後の行を取得できます

    または、名前付きパイプ(シェル)または特定のファイル記述子( csh ではない)を使用します )その印刷用


    Perlスクリプトがその名前を出力すると、変数に割り当てることができます シェルスクリプトで

    #!/bin/csh
    set DIR `perl -e'print "dir_name"'`
    
    

    bash にいる間  

    #!/bin/bash    
    DIR="$(perl -e'print "dir_name"')"
    
    

    ここで、 $(...)  コマンドの置換には推奨されます。

    ただし、Perlスクリプトからコンソールに出力されるその他の印刷物は処理する必要があります

    1つの方法は、その印刷以外のPerlスクリプトのすべての出力をリダイレクトすることです。コマンドラインオプションで制御できるもの(リダイレクト先のファイル名、印刷できるシェルスクリプト)

    または、Perlのすべての出力を取得してコンソールに渡します。最後の行は必要な「リターン」です。これは、Perlスクリプトに最後の(おそらく END  ブロック)。プログラムの出力は、完了後にシェルスクリプトから出力することも、出力時に1行ずつ出力することもできます。

    または、名前付きパイプ (両方のシェル)または特定のファイル記述子( bash  のみ)Perlスクリプトがその情報を出力できる場所。この場合、ストリームはコンソールに直接送られます。

    質問は明示的に csh に言及しています  以下に示します。しかし、シェルスクリプトは bash ではるかに優れているという古くて使い古された事実を繰り返さなければなりません。   csh よりも 。再考することを強くお勧めします。

    バッシュ

    プログラムの出力をそのままコンソールに出力する必要がある場合は、1行ずつ取得して印刷します

    #!/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スクリプト(上記のデモの1ライナーではなく)を使用して、コマンドラインオプションとしてfd番号を渡します。スクリプトは、そのオプションで呼び出された場合にのみこれを行うことができます。

    または、 csh の場合と非常によく似た名前付きパイプを使用します  未満。プログラムの STDOUT を操作する場合、ここでおそらく最適です。  あなたの好みではありません。

    csh

    プログラムの(完成した)出力を1行ずつ繰り返します

    #!/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"
    
    

    FIFOコマンドは書き込まれるまでブロックするため、Perlコマンドはバックグラウンドにありますそして 読んだ。シェルスクリプトが perl ... を待つ場合  Perlスクリプトを完了すると、FIFOへの書き込み中にブロックされるため(読み取り中でないため)、シェルは読み取りできません。デッドロックします。また、サブシェルにあり、 ( ) 、そのため、バックグラウンドジョブに関する情報の印刷を回避します。

    ザ・ --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 
    & )
    
    

    (読みやすくするために線で区切ってあります)

あなたの答え