web-dev-qa-db-ja.com

コードを含むファイルを<< EOF >>に分類する方法は?

cat <<EOF >>を使用してコードをファイルに出力したい:

cat <<EOF >> brightup.sh
!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
   curr=$((curr+406));
   echo $curr  > /sys/class/backlight/intel_backlight/brightness;
fi
EOF

しかし、ファイルの出力を確認すると、次のようになります。

!/bin/bash
curr=1634
if [  -lt 4477 ]; then
   curr=406;
   echo   > /sys/class/backlight/intel_backlight/brightness;
fi

単一引用符を付けてみましたが、出力には単一引用符も含まれています。この問題を回避するにはどうすればよいですか?

72
UberNate

最小限の変更のみが必要です。 <<の後のヒアドキュメント区切り文字を単一引用符で囲みます。

cat <<'EOF' >> brightup.sh

または同等にバックスラッシュでエスケープします:

cat <<\EOF >>brightup.sh

引用符を付けない場合、ヒアドキュメントは変数置換を受け、バックティックは評価されるなど、あなたが発見したようになります。

すべてではなく一部の値を展開する必要がある場合は、防止する値を個別にエスケープする必要があります。

cat <<EOF >>brightup.sh
#!/bin/sh
# Created on $(date # : <<-- this will be evaluated before cat;)
echo "\$HOME will not be evaluated because it is backslash-escaped"
EOF

生産します

#!/bin/sh
# Created on Fri Feb 16 11:00:18 UTC 2018
echo "$HOME will not be evaluated because it is backslash-escaped"

@ fedorqui で示唆されているように、man bashの関連セクションは次のとおりです。

Here Documents

このタイプのリダイレクションは、区切り文字のみ(末尾ブランクなし)を含む行が表示されるまで、現在のソースから入力を読み取るようシェルに指示します。その時点までに読み取られたすべての行は、コマンドの標準入力として使用されます。

ヒアドキュメントの形式は次のとおりです。

      <<[-]Word
              here-document
      delimiter

Wordでは、パラメーターの展開、コマンドの置換、算術展開、またはパス名の展開は実行されません。 Wordの文字が引用符で囲まれている場合、区切り文字はWordで引用符を削除した結果であり、ヒアドキュメントの行は展開されません。 Wordが引用符で囲まれていない場合、ヒアドキュメントのすべての行は、パラメーター展開、コマンド置換、および算術展開の対象となります。後者の場合、文字シーケンス\は無視され、文字\、$、および `を引用するには\を使用する必要があります。

114
tripleee

または、EOFマーカーを使用して、最初のマーカーを引用符で囲む必要があるため、展開は行われません。

#-----v---v------
cat <<'EOF' >> brightup.sh
#!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
   curr=$((curr+406));
   echo $curr  > /sys/class/backlight/intel_backlight/brightness;
fi
EOF

IHTH

18
shellter

これは機能するはずです。私はそれをテストしましたが、期待通りに機能しました。拡張、置換、または何が起きたのかはわかりません。

cat <<< '
#!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
  curr=$((curr+406));
  echo $curr  > /sys/class/backlight/intel_backlight/brightness;
fi' > file # use overwrite mode so that you don't keep on appending the same script to that file over and over again, unless that's what you want. 

以下を使用しても機能します。

cat <<< ' > file
 ... code ...'

また、<< EOFなどのヒアドキュメントを使用する場合、置換や変数の展開などが行われることに注意してください。そのため、次のようなことを行います。

cat << EOF > file
cd "$HOME"
echo "$PWD" # echo the current path
EOF

常に変数$HOMEおよび$PWDが展開されます。したがって、ホームディレクトリが/home/foobarで、現在のパスが/home/foobar/binである場合、fileは次のようになります。

cd "/home/foobar"
echo "/home/foobar/bin"

予想される代わりに:

cd "$HOME"
echo "$PWD"
9
Alexej Magura