AWK: mengapa $ (cat) berfungsi untuk stdin, tetapi $ * tidak?

9
echo '((3+(2^3)) * 34^2 / 9)-75.89' | awk "BEGIN{ print $(cat) }"

Sintaks di atas berfungsi dengan baik dengan hasil yang dihitung '1337'.

echo '((3+(2^3)) * 34^2 / 9)-75.89' | awk "BEGIN{ print $* }"

Tetapi sintaks di atas tidak bekerja, meskipun tidak ada kesalahan.

Mohon saran.

pengguna58029
sumber

Jawaban:

13

The $(command)sintaks akan kembali output dari command. Di sini, Anda menggunakan catprogram yang sangat sederhana yang tugasnya hanya menyalin semuanya dari input standar (stdin) ke output standar (stdout). Karena Anda menjalankan awkskrip di dalam tanda kutip ganda, yang $(cat)diperluas oleh shell sebelum para awkskrip dijalankan, sehingga membaca echooutput ke stdin dan salinan sepatutnya untuk stdout. Ini kemudian diteruskan ke awkskrip. Anda dapat melihat ini beraksi dengan set -x:

$ set -x
$ echo '((3+(2^3)) * 34^2 / 9)-75.89' | awk "BEGIN{ print $(cat) }"
+ echo '((3+(2^3)) * 34^2 / 9)-75.89'
++ cat
+ awk 'BEGIN{ print ((3+(2^3)) * 34^2 / 9)-75.89 }'
1337

Jadi, awksebenarnya berjalan BEGIN{ print ((3+(2^3)) * 34^2 / 9)-75.89 }'yang mengembalikan 1337.

Sekarang, $*ini adalah variabel shell khusus yang diperluas ke semua parameter posisi yang diberikan ke skrip shell (lihat man bash):

   *      Expands to the positional parameters, starting from one.  When the expan
          sion  is not within double quotes, each positional parameter expands to a
          separate word.  In contexts where it is performed, those words  are  sub
          ject  to  further word splitting and pathname expansion.  When the expan
          sion occurs within double quotes, it expands to a single  word  with  the
          value  of each parameter separated by the first character of the IFS spe
          cial variable.  That is, "$*" is equivalent to "$1c$2c...",  where  c  is
          the  first  character of the value of the IFS variable.  If IFS is unset,
          the parameters are separated by spaces.  If IFS is null,  the  parameters
          are joined without intervening separators.

Namun, variabel ini kosong di sini. Oleh karena itu, awkskrip menjadi:

$ echo '((3+(2^3)) * 34^2 / 9)-75.89' | awk "BEGIN{ print $* }"
+ awk 'BEGIN{ print  }'
+ echo '((3+(2^3)) * 34^2 / 9)-75.89'

The $*memperluas ke string kosong, dan awkdiperintahkan untuk mencetak string kosong, dan ini adalah mengapa Anda tidak mendapatkan output.


Anda mungkin hanya ingin menggunakan bc:

$ echo '((3+(2^3)) * 34^2 / 9)-75.89' | bc
1336.11
terdon
sumber
Sebaiknya gunakan bc -l, jika tidak Anda akan mendapatkan perbedaan yang Anda posting di atas (di mana hasil divisi telah terpotong).
cmbuckley
@ cmbuckley Saya mencoba membuatnya mencetak 1337 dengan bermain-main dengan scale=(saya berasumsi OP ingin bermain dengan leetspeak) tetapi saya tidak dapat menemukan cara. bc -lkembali 1336.99888888888888888888ke sistem saya.
terdon