b.l0g.jp     About     Archive     Feed

bshでのクォーテーションの入れ子

特殊文字(?など)をそのまま文字として扱いたい場合などに、シングルクォーテーション(‘)やダブルクォーテーション(“)で文字をくくる。

  • 「”」でくくった文字列は、その中に特殊文字が含まれているならそれを展開する。
  • 「’」でくくった文字列は、その中に特殊文字が含まれていてもそれを展開せず、そのまま表示する。
  
[hoge@symf test]$ abc=3
    
↑ abcという変数に3を代入
  
[hoge@symf test]$ echo $abc
  
3
    
↑ abcという変数の中身を表示
  
[hoge@symf test]$ echo "$abc"
  
3
    
↑ 「"」は特殊文字を展開するので変数として扱われるので、上に同じ
  
[hoge@symf test]$ echo '$abc'
  
$abc
    
↑ 「'」は特殊文字をそのまま表示する
  

クォーテーションを入れ子にする際には、シングルとダブルで少しやり方が違う。「man bash」の「クォート」の項には以下のように書かれている。

シングルクォートで文字を囲むと、クォート内部のそれぞれの文字は文字としての値を 保持 します。シングルクォートの間にシングルクォートを置くことはできません。これはバックスラッシュを前に付けても同じです。

ダブルクォートで文字を囲むとクォート内部の全ての文字は文字としての値を保持しま すが、 $, ‘, \ は例外となります。 $ と ‘ はダブルクォートの内部でも特殊な意味を失いません。バックスラッシュの場合は、次の文字が $, ‘, “, \,のいずれかである 場合に限り特殊な意味を失いません。前にバックスラッシュを付ければ、ダブルクォート文字をダブルクォートによるクォートの内部でクォートできます。

つまりこういうこと。

  
[hoge@symf test]$ ssh server "psql -c \"create database test with ENCODING = 'UTF8' ;\" "
    
↑ 「"」の中に「\"」があるので、これは成功

[hoge@symf test]$ ssh server 'psql -c \"create database test with ENCODING = 'UTF8' ;\" '
    
↑ 「'」の中では「\」をつけてもダメなので、これは失敗
  

create databaseじゃなくてcreatedbを使えば、クォートを入れ子にしなくてもいいって?あくまで例ですから (`・ω・´)キリッ

shのwhileループでファイルを読み、中でsshを実行すると1回しかループしない

シェル(sh)スクリプトネタ。

while 文で以下のように指定すると、行ごとにファイルを読み込むことができる。

  
#!/bin/sh

\# ファイルを1行ずつ読み込んで表示

TESTFILE=./hoge.txt

while read line
  
do
      
echo $line
  
done < $TESTFILE
  

しかし、 while ループの中で ssh や rsh を実行すると、読み込むファイルが複数行あっても、1行目しか処理されない。

  
#!/bin/sh

\# TESTFILEが複数行あっても1行目のみ処理されてループ終了

while read line
  
do
      
ssh 192.168.0.1 touch $line
  
done < $TESTFILE
  

SSH を実行すると、標準入力がそちらに振り向けられるため、read で読んだ1行のみならず、ファイル全体が SSH に渡されてしまう。従って、SSH を実行した後はもう読める行がないので while ループは1回で終了してしまう。

これを防ぐには、ssh に -n オプションを付け、/dev/null をリダイレクトし、標準入力をリダイレクトしないようにする。

  
#!/bin/sh

\# TESTFILEが複数行あればその行数分処理が実行される

while read line
  
do
      
ssh -n 192.168.0.1 touch $line
  
done < $TESTFILE
  

なおこれは rsh コマンドでも同じ仕様になっているようだ。

なぜ1行目だけで終わってしまうのか分からずうんうんうなってたら、この本に書いてあった。

ディレクトリをディレクトリにマウント

Linuxで、ディスクデバイスではなく、ディレクトリをディレクトリにマウントしたい時は

  
mount -bind マウントしたいディレクトリ マウントポイント
  

fstabに書いてしまうときは以下のように書く。

  
マウントしたいディレクトリ マウントポイント none bind 0 0
  

例えば /home を /hoge/home としてマウントしたい時は

  
/home /hoge/home none bind 0 0
  

なお、マウントしたいディレクトリ(上の例では/hoge)よりも後にこの行を書かないと、マウントできないので注意。