新しいファイルをリダイレクトするcatコマンドがすぐに実行されるのはなぜですか?

新しいファイルをリダイレクトするcatコマンドがすぐに実行されるのはなぜですか?

次のように後で呼び出すことができるbashファイルを生成したいと思います。

cat <<-SCRIPT >test-$$
        #!/bin/bash
        osType=$(grep -Po '^NAME="\K[^"]*' /etc/os-release)
        if [ "$osType" = ...]
        then
            ...
        fi
        exit
    SCRIPT

デバッグすると、grepコマンドは常に正しい方法で実行されます。なぜですか?また、awkと同じエラーを試してみました。

しかし、私がそうするなら

cat <<-SCRIPT >test-$$
        #!/bin/bash
        rpm -q somepackage > test-$$
        rm test-$$-lock
        exit
    SCRIPT

rpmコマンドが正しい方法で実行されるのを見ることができませんか? test-$$とtest-$$-lockも同じ$$を持っていますか?

ベストアンサー1

here-docのようなものは<<-SCRIPT拡張が内部で処理されるため、二重引用符で囲まれた文字列のように動作します。これを防ぐために、区切り文字を引用してください。

$ cat <<EOF
1+1 = $((1+1))
EOF

1+1 = 2

そして

$ cat <<'EOF'
1+1 = $((1+1))
EOF

1+1 = $((1+1))

だからここにあります:

cat <<-SCRIPT >test-$$
        ...
        osType=$(grep -Po '^NAME="\K[^"]*' /etc/os-release)

コマンドはgrepコマンド置換にあり、SCRIPT引用符なしで処理されるため、ここでドキュメントを使用すると実行されます。

一方、ここでは:

cat <<-SCRIPT >test-$$
        #!/bin/bash
        rpm -q somepackage > test-$$
        rm test-$$-lock
        exit
    SCRIPT

コマンド置換がないため、コマンドは実行されません。このrpm -q somepackageセクションはテキストだけです。ただし、引用符のない区切り文字を使用すると、$$ここのドキュメントの内部は出力ファイル名で使用されているのと同じ値にすぐに拡張されます。つまり、現在のシェルのPIDが1234の場合、このコマンドはインクルードラインをcat生成します。test-1234rpm -q somepackage > test-1234

引用符で囲まれた区切り文字を使用すると、そのまま残り、$$結果はインクルードと呼ばれtest-1234ますrpm -q somepackage > test-$$test-1234今スクリプトで実行すると$$拡張されますそれシェルのPIDが使用されます。ファイルの作成に使用された値と異なる場合があります。

それにもかかわらず、$$同じrpm .. > test-$$rm test-$$-lockに拡張されます。

おすすめ記事