AWK: perché $ (cat) funziona con stdin, ma $ * no?


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

La sintassi sopra funziona bene con il risultato calcolato '1337'.

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

Ma la sintassi sopra non funziona, sebbene non ci siano errori.

Si prega di avvisare.

Risposte:


13

La $(command)sintassi restituirà l'output di command. Qui stai usando il catprogramma molto semplice il cui unico lavoro è copiare tutto dallo standard input (stdin) allo standard output (stdout). Poiché si esegue lo awkscript tra virgolette doppie, $(cat)viene espanso dalla shell prima che lo awkscript venga eseguito, quindi legge l' echooutput nel suo stdin e lo copia debitamente nel suo stdout. Questo viene quindi passato allo awkscript. Puoi vederlo in azione con 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

Quindi, in awkrealtà è in esecuzione BEGIN{ print ((3+(2^3)) * 34^2 / 9)-75.89 }'che restituisce 1337.

Ora, $*è una variabile di shell speciale che si espande a tutti i parametri posizionali dati a uno script di shell (vedi 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.

Tuttavia, questa variabile è vuota qui. Pertanto, lo awkscript diventa:

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

Si $*espande in una stringa vuota e awkviene detto di stampare una stringa vuota, ed è per questo che non si ottiene alcun output.


Potresti voler semplicemente usare bcinvece:

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

Probabilmente dovresti usare bc -l, altrimenti otterrai la discrepanza che hai pubblicato sopra (dove il risultato della divisione è stato troncato).
cmbuckley,

@cmbuckley Stavo cercando di farlo stampare con il 1337 giocando scale=(suppongo che l'OP voglia giocare con leetspeak) ma non sono riuscito a trovare un modo. bc -lritorna 1336.99888888888888888888sul mio sistema.
terdon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.