web-dev-qa-db-ja.com

bashの変数を使用したエコーコマンドのエコー

さて、ここで私たちが話すときに苦労しているものがあります。変数を使用したエコーコマンドのエコー。

echo "creating new script file."
echo "#!/bin/bash" > $servsfile
echo "read -p "Please enter a service: " ser " >> $servfile
echo "servicetest=`getsebool -a | grep ${ser}` " >> $servfile
echo "if [ $servicetest > /dev/null ];then " >> $servfile
echo "echo "we are now going to work with ${ser}" " >> $servfile
echo "else" >> $servfile
echo "exit 1" >> $servfile
echo "fi" >> $servfile

私の目標は、エコーコマンドを使用してスクリプトを作成し、後で実行することです。変数を維持しながらエコー/読み取りコマンドをエコーする方法を理解する必要があります。

編集:変数は、その中にあるものを新しいファイルに転送する必要があります。

20
David

直接の問題は、引用符を使用することです:二重引用符を使用すると、変数参照はinstantly expandedになります。おそらくあなたが望むものではありません。

代わりにsingle quotesを使用します-単一引用符内の文字列は、シェルによって展開または解釈されません。

selective文字列内の展開-つまり、いくつかの変数参照を展開しますが、他の変数参照は展開しません-二重引用符を使用しますが、_$_の参照をプレフィックスしますnot _\_で展開したい;例、_\$var_)。

ただし、単一のhere-doc [ument]を使用することをお勧めします。これにより複数行のstdin入力をその場で作成、自己選択デリミタの2つのインスタンスで囲まれ、先頭に_<<_が先頭にあり、末尾に1行に1つ-最初の列から開始。 _Here Documents_を_man bash_または http://www.gnu.org/software/bash/manual/html_node/Redirections.html で検索します。

quote the here-doc delimiter(以下のコードのEOF)の場合、変数参照も- not expanded。 @chepnerが指摘しているように、この場合、引用のmethodを自由に選択できます。区切り文字を単一引用符で囲みますor二重引用符、orデリミタ内の1文字を_\_で単純に任意にエスケープします:

_echo "creating new script file."

cat <<'EOF'  > "$servfile"
#!/bin/bash
read -p "Please enter a service: " ser
servicetest=`getsebool -a | grep ${ser}` 
if [ $servicetest > /dev/null ]; then 
  echo "we are now going to work with ${ser}"
else
  exit 1
fi
EOF
_

@BruceKが注記しているように、here-doc区切り文字の前に_-_を付けることができます(この例に適用されるのは_<<-"EOF"_)先頭にtabsstripped。here-docの実際の内容を見分けやすくするインデントを可能にします。ただし、これは実際のtab文字でのみ機能し、先頭のスペースでは機能しないことに注意してください。

以下のスクリプトのコンテンツに関する後付けと組み合わせてこの手法を使用すると、次のようになります(繰り返しますが、実際のtab charsを使用して、各here-docコンテンツ行を削除する必要があります)。

_cat <<-'EOF' > "$servfile"
    #!/bin/bash
    read -p "Please enter a service name: " ser
    if [[ -n $(getsebool -a | grep "${ser}") ]]; then 
      echo "We are now going to work with ${ser}."
    else
      exit 1
    fi
EOF
_

最後に、bashでも通常の単一引用符または二重引用符で囲まれた文字列は複数行にまたがることができますですが、タブストリッピングやラインブロックスコープの利点は得られません。 as everythingは、引用符内では文字列の一部になります。

したがって、次の_#!/bin/bash_が最初の行になるために、最初の_'_ immediatelyに従う必要があることに注意してください。

_echo '#!/bin/bash
read -p "Please enter a service: " ser
servicetest=$(getsebool -a | grep "${ser}")
if [[ -n $servicetest ]]; then 
  echo "we are now going to work with ${ser}"
else
  exit 1
fi' > "$servfile"
_

スクリプトの内容に関する後付け:

  • 構文$(...)は、最近のコマンド置換のために_`...`_よりも優先されます。
  • grepコマンドで_${ser}_を二重引用符で囲む必要があります。値に埋め込みスペースが含まれる場合、コマンドが壊れる可能性が高いためです(または、値の読み取りにスペースや他のシェルメタキャラクターが含まれていないことを確認してください)。
  • _[[ -n $servicetest ]]_を使用して、_$servicetest_が空かどうかをテストします(または、条件内で直接コマンド置換を実行します)-_[[ ... ]]_-bashの優先フォーム-の破損を防ぎます_$servicetest_にスペースが埋め込まれている場合は条件付き。 stdout出力が渡されないため、条件付き(_[ ... ]_または_[[ ... ]]_のいずれかでstdout出力を抑制する必要はありません。したがって、_> /dev/null_は冗長です(つまり、コマンドで条件内の置換、stderr output ISパススルー)。
22
mklement0

単一引用符を使用するだけです。

$ echo "$TEST"
test
$ echo '$TEST'
$TEST

一重引用符の中では、特殊文字は特別ではなく、単なる通常の文字です。

13
Mihai
echo "echo "we are now going to work with ${ser}" " >> $servfile

引用符内のすべての "を\でエスケープします。\ $ servicetestなどの変数でもこれを行います。

echo "echo \"we are now going to work with \${ser}\" " >> $servfile    
echo "read -p \"Please enter a service: \" ser " >> $servfile
echo "if [ \$servicetest > /dev/null ];then " >> $servfile
8
GoinOff