サブシェルはファイルの代わりに変数としてデータを返し、同時に別のログを出力できますか?

サブシェルはファイルの代わりに変数としてデータを返し、同時に別のログを出力できますか?

次のJavaScriptがあるとします。

    const something = doSomething();
    
    function doSomething() {
        console.log("About to do something");
        
        const a = doSomethingElse();
        if (a == "dog") {
            console.log("Worked");
            console.log("Now let's do xyz");
            return "cat";
        } else {
            console.log("failed for some reason");
            return "horse";
        }
    }
    
    function doSomethingElse() {
        console.log("About to do more");
        console.log("Done doing more stuff");
        
        return "dog";
    }

Bashでこれをどのように達成できますか?後で使用するためにログをファイルに保存するのではなく、リアルタイムで見たいですか?私は次のことを考えていましたが、すべてが混在しており、bashのreturnキーワードは他の目的に使用され、文字列を受け入れません。

    something=$(doSomething);
    
    function doSomething() {
        console_log "About to do something";
        
        a=$(doSomethingElse);
        if [[$a = "dog"]]; then
            console_log "Worked";
            console_log "Now let's do xyz";
            echo "cat"; # Wish I could do return "cat" ...
        else
            console_log "failed for some reason";
            echo "horse"; # Wish I could do return "horse" ...
        fi;
    }
    
    function doSomethingElse() {
        console_log "About to do more";
        console_log "Done doing more stuff";
        
        echo 'dog'; #Wish I could do return "dog" ...
    }
    
    function console_log() {
        #Is echo the right thing, or tee, or something else ?
        echo $1;
    }

これを達成するために複数の出力ストリームがありませんか?または、変数を代入するために$()に代わるものはありますか? Tシャツ、&*、&?で遊んでみました。そして3> 1項目はすべて理解できません... :(

CentOS 7.9にbash 4.2.46があります。

あなたの助けをいただきありがとうございます:)

答え1

大丈夫でしょう。

#! /bin/bash -

doSomething() {
    print_err "About to do something"

    a="$(doSomethingElse)"
    if [[ "$a" = "dog" ]]; then
        print_err "Worked"
        print_err "Now let's do xyz"
        printf '%s' "cat"
    else
        print_err "failed for some reason"
        printf '%s' "horse"
    fi
}

doSomethingElse() {
    print_err "About to do more";
    print_err "Done doing more stuff";
    printf '%s' 'dog'
}

print_err() {
    # Print to stderr as we do this in functions
    # that print result to stdout
    printf '%s\n' "$1" >&2
}

something="$(doSomething)"
# Making it readonly would be somewhat similar to const
readonly something

printf '%s\n' "$something"

必要:

一般的に言うと:

それ以外の場合は、[[交換すると仕様[が適用されますsh「sh互換」とはどういう意味ですか?

また、変数の範囲を見てください。ksh bashとzshをダッシュ​​するためにデフォルトのコマンドを移植する方法はありますか?

あなたのようにすることができます、完成した:

set_something() {
    something='cat'
}

set_something
printf 'something="%s"\n' "$something"

流れ

JavaScriptはストリームを処理できませんが、シェルは処理できます。単純化するには:

  • readfrom stdin, ファイル記述子0(標準)
  • writestdout、ファイル記述子(1標準出力)
  • writestderr、ファイル記述子(2標準エラー)

また、新しいファイルを開く、ファイルを読み書きするなども可能です。

興味があるかもしれません/dev/stdin、/dev/stdout、および/dev/stderrの移植性はどのくらいですか?


戻り値。

Bash 関数は文字列を「返す」ことはありません。人がそうするとき:

foo="$(some command)"

some command標準出力をに割り当てますfoo。リダイレクトを変更しない場合ビデータコードで印刷すると、次のように表示されます。

# In doSomething():
    printf 'a="%s"\n' "$a" >&2

# At end:
printf '"%s"\n' "$something"

あなたは得るでしょう:

a="About to do more
Done doing more stuff
dog"
something="About to do something
failed for some reason
horse"

ご覧のとおり、出力全体が割り当てられます。

後ろに「固定する」一つできるstderrをstdoutにリダイレクトして両方をキャプチャしますstdoutstderr

foo="$(some command 2>&1)"

終了コード

ただし、シェル関数には他のプログラムと同様に終了コードがあります。明示的な戻り値がない場合は、関数内で実行された最後のコマンドの終了状態です。0問題ありません。他のすべてはテストのバグと見なされます。

簡単な例:

#! /bin/bash -

foo() {
    printf 'I am foo\n'
    return 1
}
greetings() {
    if [ "$1" = "hi" ]; then
        printf 'Hello\n'
    else
        printf 'I do not know what to do with %s\n' "$1"
        return 12
    fi
}
if foo; then
    printf 'OK\n'
else
    printf 'FAIL\n'
fi

printf '\n## Try greetings "yo":\n'
greetings yo
ecode=$?
printf 'greetings() returned %d\n' "$ecode"

printf '\n## Try greetings "hi":\n'
greetings hi
ecode=$?
printf 'greetings() returned %d\n' "$ecode"

結果:

I am foo
FAIL

## Try greetings "yo":
I do not know what to do with yo
greetings() returned 12

## Try greetings "hi":
Hello
greetings() returned 0

助けshellcheck

完璧ではありませんが、スクリプトを確認するのに多くの役に立ちます。

コマンドラインツールとして使用できます。オンラインでコードを貼り付ける、またはエディタに統合します。

たとえば、ALE で Vim を使用している場合、shellcheckVim がインストールされている場合に起動します。ただし、ディストリビューションにバンドルされているパッケージは多少古いかもしれません。 Ubuntu 18.04を例にとると、v0.4.6を使用してください。

https://github.com/koalaman/shellcheck

一般的なシェルスクリプト

他の人と一緒にプレイしてくださいbash。学習に便利です。いつもやりたいことを考えてください。たとえば、テキスト処理には他のツールを使用することがほぼ常に優れています。その後、シェルスクリプトを使用して互いに貼り付けることができます。パイプなどを使用してください - unices機能の一部です。ここでは、たとえば、、、、、、、、、、、、、、、、、、、、、、、、、sortなどです。joincuttrpasteuniqfindgrepcatdatetailheadxargswcfoldcolumnpaste

インタラクティブシェルスクリプトはそれを使用できるだけでなく、さまざまな機能でシェルを拡張できます。

perlより高度なデータ型と複雑さのために、、および他のさまざまな種類pythonを使用できます。通常、これは低レベルでシステムを理解するのに非常に良い方法です。cc

awk背中はsedまた、テキスト操作に非常に強力で有用であり、awk学習するのも簡単です。

関連情報