AWK: чому $ (cat) працює для stdin, але $ * не працює?


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

Вищенаведений синтаксис працює добре з обчисленим результатом '1337'.

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

Але вищевказаний синтаксис не працює, хоча помилки немає.

Раджу Plz.

Відповіді:


13

$(command)Синтаксис повертає висновок command. Тут ви використовуєте дуже просту catпрограму, єдине завдання якої - скопіювати все зі стандартного вводу (stdin) на стандартний вихід (stdout). Так як ви запускаєте awkскрипт в подвійних лапках, то $(cat)розширюється оболонки передawk тим скрипт запускається, так що він читає echoвисновок в його стандартне введення і належним чином копії його в стандартний висновок. Потім це передається awkсценарію. Ви можете бачити це в дії з 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

Отже, awkнасправді працює, BEGIN{ print ((3+(2^3)) * 34^2 / 9)-75.89 }'який повертає 1337.

Тепер, $*це спеціальна змінна оболонки, яка розширюється на всі позиційні параметри, задані сценарію оболонки (див. 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.

Однак ця змінна тут порожня. Тому awkсценарій стає:

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

$*Розширюється символом нового рядка, і awkсказав , щоб надрукувати порожній рядок, і тому ви не отримаєте ніякого висновку.


Ви можете просто використовувати bcзамість цього:

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

Ймовірно, слід використовувати bc -l, інакше ви отримаєте розбіжність, яку ви розмістили вище (там, де результат ділення був усічений).
cmbuckley

@cmbuckley Я намагався змусити його надрукувати 1337, граючи з scale=(я припускаю, що ОП хоче грати з leetspeak), але не знайшов способу. bc -lповертається 1336.99888888888888888888в мою систему.
тердон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.