AWK: tại sao $ (cat) hoạt động cho stdin, nhưng $ * thì không?


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

Cú pháp trên hoạt động tốt với kết quả được tính toán '1337'.

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

Nhưng cú pháp trên không hoạt động, mặc dù không có lỗi.

Xin tư vấn.

Câu trả lời:


13

Các $(command)cú pháp sẽ trở lại với sản lượng command. Ở đây, bạn đang sử dụng catchương trình rất đơn giản với công việc duy nhất là sao chép mọi thứ từ đầu vào tiêu chuẩn (stdin) sang đầu ra tiêu chuẩn (stdout). Kể từ khi bạn đang chạy các awkkịch bản bên trong dấu ngoặc kép, những $(cat)được mở rộng bằng vỏ trước các awkkịch bản được chạy, vì vậy nó đọc echora vào stdin và bản sao hợp lệ nó để stdout của nó. Điều này sau đó được chuyển đến awkkịch bản. Bạn có thể thấy điều này trong hành động với 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

Vì vậy, awkthực sự đang chạy BEGIN{ print ((3+(2^3)) * 34^2 / 9)-75.89 }'mà trả về 1337.

Bây giờ, $*biến shell là đặc biệt mở rộng cho tất cả các tham số vị trí được cung cấp cho tập lệnh shell (xem 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.

Tuy nhiên, biến này là trống ở đây. Do đó, awkkịch bản trở thành:

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

Việc $*mở rộng thành một chuỗi trống và awkđược yêu cầu in một chuỗi trống và đây là lý do tại sao bạn không nhận được đầu ra.


Bạn có thể chỉ muốn sử dụng bcthay thế:

$ echo '((3+(2^3)) * 34^2 / 9)-75.89' | bc
1336.11

Có lẽ nên sử dụng bc -l, nếu không, bạn sẽ nhận được sự khác biệt mà bạn đã đăng ở trên (nơi kết quả của việc phân chia đã bị cắt ngắn).
cmbuckley

@cmbuckley Tôi đã cố gắng để nó được in 1337 bằng cách chơi xung quanh scale=(Tôi cho rằng OP muốn chơi với leetspeak) nhưng tôi không thể tìm ra cách. bc -ltrả 1336.99888888888888888888về hệ thống của tôi
terdon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.