シェルスクリプトでの文字列の評価


8

私はこのbashシェルスクリプトガイドに従っています:

数値比較のセクションでは、例を挙げています。

anny > num=`wc -l work.txt`

anny > echo $num
201

anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi

上記のように思われるのは、コマンドの文字列をbash変数に格納してから、変数に対してエコーを呼び出すことです。発生しているように見えるのは、文字列が評価されてwcコマンドが実行され、制御端末に行数が返されることです。

それでは、Ubuntu 12.04で端末を起動して、同様のことを試してみます。

$ touch sample.txt && echo "Hello World" > sample.txt
$ cat sample.txt
Hello World
$ num='wc -l sample.txt'
echo $num
wc -l sample.txt

文字列を評価せずに行数を返します。これは文字列をターミナルにエコーしました。なぜ異なる結果が得られたのですか?


numは文字列を割り当てられることはありませんことに注意してくださいwc -l work.txt、代わりにそれは数201を割り当てられている
イグニス

回答:


2

式を評価するには、バックティックを使用する必要があります。

$ num=`wc -l sample.txt`
$ echo $num
1 sample.txt

出力に「1」のみを表示したい場合は、コマンドを使用します

$ num=`cat sample.txt | wc -l`
$ echo $num
1

そしてまた働く:

$ num=`wc -l < sample.txt`
$ echo $num
1

詳細については、コマンドラインの二重引用符 ""、単一引用符 ''、およびバッククォート ´´の違いを参照してください


数値「1」だけでなく「1 sample.txt」を取得する理由は何ですか?
JohnMerlino 2014年

これがwcコマンドの動作方法です。お試しくださいcat sample.txt | wc -l
Danatela 2014年

wc -lは、ファイル名とともにファイルに存在する行数を表示します。
Avinash Raj 14年

5

その記号に注意してください:

一重引用符

   Enclosing characters in single quotes preserves the  literal  value  of
   each character within the quotes.  A single quote may not occur between
   single quotes, even when preceded by a backslash.

そして

`

逆引用

   Command substitution allows the output of a command to replace the com
   mand name.  There are two forms:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.

したがって、バッククォートはコマンドの結果を標準出力に返しています。それが理由です

`wc -l sample.txt`

コマンドの結果を返しますが、

「wc -l sample.txt」

通常の文字列として「wc -l sample.txt」を返すだけです

例としてこれを行うことを検討してください:

$ A='wc -l /proc/mounts'
$ B=`wc -l /proc/mounts`
$ C=$(wc -l /proc/mounts)

そして、3つの変数すべてをエコーし​​ます。

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts

4

コマンドの出力を変数にキャプチャする場合は、バッククォートを使用するか``、コマンドをで囲む必要があります$()

$ d=$(date)
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014
$ d=`date`
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014

文字列は、エコーするときではなく、変数宣言の瞬間に実際に評価されることに注意してください。コマンドは実際には、$()またはバッククォート内で実行され、そのコマンドの出力は変数の値として保存されます。

一般に、$()廃止予定のバックティックの代わりに常に使用する必要があります。互換性の理由と制限がさらに大きいためです。たとえば、コマンドをバックティック内にネストすることはできませんが、次のようにできます$()

$ echo $(date -d $(echo yesterday))
Sun Mar 16 10:26:07 CET 2014

回避すべき理由の詳細については、U&Lのこのスレッドを参照してください``


1
私はスクリプトがを好むはずであることに同意$( )` `ます。しかし、wagが言うように、バッククォートネストします。echo $(date -d $(echo yesterday))になるecho `date -d \`echo yesterday\``; echo $(echo $(date -d $(echo yesterday)))になりecho `echo \`date -d \\\`echo yesterday\\\`\``ます。私はこれをあなたの論文に反抗するのではなく、それを強化するために言います:エスケープされた内部バッククォートは` `構文がしばしば認められるよりも強力になりますが、特別な扱い\は奇妙で、驚くべきであり、推論するのが難しいです。では$( )何を参照してくださいあなたが得るもの通常です。
Eliah Kagan 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.