ubuntuusers.de

awk - Operation auf jedes Feld anwenden

Status: Gelöst | Ubuntu-Version: Ubuntu 14.04 (Trusty Tahr)
Antworten |

sappy

Anmeldungsdatum:
24. Januar 2012

Beiträge: Zähle...

Hallo,

ich habe eine Zeile mit vielen Zahlen: 423 325 4534 2132 132 3424 .... (FieldSep. ist 1 Whitespace) als Output direkt in der Kommandozeile. Muss nun eine arithmetische Operation auf alle Zahlen / bzw. Felder anweden. Z.b. alle mit 4 multiplizieren und dann formatiert (z.B. rechtsbündig mit 10-er Breite) ausgeben. Dachte da sofort an awk. Das klappt recht gut, wenn ich einzelne Felder anspreche:

1
... | awk '{ printf "%+10s%+10s%+10s\n", $1*4, $2*4, $3*4}'

Nun will ich ja nicht alle 300 Zahlen so ansprechen. $0 durch 4 zu teilen klappt leider nicht. Heißt ich muss mit einer Schleife ran in der ich die NF-Variable nutze?

Lg sappy

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17623

Wohnort: Berlin

Sicher mit awk auch möglich, aber wozu?

1
2
echo 423 325 4534 2132 132 3424 | tr ' ' '\n' | while read v; do printf "%+10s" $(($v*4)); done; echo
      1692      1300     18136      8528       528     13696

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4694

Wohnort: Berlin

Das tr könnte man in der Bash noch einsparen wenn man dem read sagt, dass das Trennzeichen ein Leerzeichen ist:

1
echo 423 325 4534 2132 132 3424 | while read -r -d' ' v; do printf "%+10s" $((v*4)); done; echo

Wozu man awk eventuell bräuchte ist wenn man durch 4 teilen und Nachkommastellen haben möchte. sappy ist sich da mit multiplizieren oder teilen im Beitragstext anscheinend ja nicht so ganz sicher. ☺

Statt awk könnte man natürlich auch dc, bc, oder etwas anderes in der Richtung nehmen.

misterunknown Team-Icon

Ehemalige
Avatar von misterunknown

Anmeldungsdatum:
28. Oktober 2009

Beiträge: 4403

Wohnort: Sachsen

Der Vollständigkeit halber:

echo "423 325 4534 2132 132 3424" | awk '{ for(i=1; i<=NF; i++) printf "%+10s", $i*4; }'

linuxer-nds

Anmeldungsdatum:
1. Februar 2015

Beiträge: 33

In diesem Fall ist awk auch gut geeignet. Mit einem Leerzeichen als Record Separator braucht man nicht mal einen expliziten for-Loop:

1
echo ... | awk 'BEGIN{RS=" "}{printf "%+10s",$1*4}'

sappy

(Themenstarter)

Anmeldungsdatum:
24. Januar 2012

Beiträge: 282

Hallo,

@Marc_BlackJack_Rintsch: Ja da hab ich mich vertan. Soll durch 4 werden, die ganze Geschichte. Ich werde dann also lieber das awk nehmen.

@linuxer-nds: Das ist ja interessant. Versteh da allerdings nicht warum man dann mit $1 ansetzen kann? Dachte, das wäre dann nur das 1. Feld? Ich habe deine Variante getestet. Es funktioniert. Nur ich muss da anscheinend echt vorsichtig sein. Als erste Zahl bekomme ich eine 0. Da stand aber gar keine Zahl die er durch 4 teilen sollte. Ich vermute folgendes: in meinem Zahlenoutput steht vor der 1. "richtigen" Zahl ein Leerzeichen. Und er hat dann da "irgendwas" genommen, wo nicht's sein sollte und dann die 0 rausbekommen? Wenn das so sein sollte, muss ich halt das Leerzeichen vor der 1. Zahl noch entfernen lassen vorher.

@misterunknown: Auch das klappt. Hier bleibt die falsche Null vorne auch weg.

Vielen Dank an euch alle schon einmal für eure schnell Hilfe!

lg sappy

linuxer-nds

Anmeldungsdatum:
1. Februar 2015

Beiträge: 33

Hallo sappy,

ja, mit einem Leerzeichen am Anfang gibt's ein Problem, weil der erste Record dann genau bis dahin geht und damit leer ist, also $0="". Auch bei mehrfachen Leerzeichen bekommt man leere Records. 😮

Ansonsten besteht jeder Record aus den Zeichen zwischen zwei Leerzeichen, und das wäre dann auch immer $1. Das Problem lässt sich vermeiden, wenn man testet, ob $1 vorhanden ist, also zB.

1
 awk 'BEGIN{RS=" "}NF==1{printf "%+10s",$1/4}'

oder

1
 awk 'BEGIN{RS=" "}$1{printf "%+10s",$1/4}'

sappy

(Themenstarter)

Anmeldungsdatum:
24. Januar 2012

Beiträge: 282

Super, danke dir linuxer-nds

lg sappy

Antworten |