Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value of an assignment in awk, ternary operator parsing in awk

Tags:

awk

I new to awk and playing around with it. When trying to use the ternary operator, at some point I wanted to execute two operations upon true condition, and as I couldn't find the syntax to do so I tried to smuggle one of the two operations inside the condition to take advantage of the lazy evaluation.

I have an input file as follow:

file.csv

A,B,C,D
1,,,
2,,,
3,,,
4,,,
5,,,
6,,,
7,,,
8,,,

And I'd like, for the sake of the exercise, to put assign B and C to 0 if A is less than 5 ; C to 1 if A is 5 or more. I guess the ternary operator is a terrible way to do this but this is not my point.

The question is: why does the following line outputs that? How does awk parse this expression ?

awk '(FNR!=1){$1<5 && $3=0 ? $2=0 : $2=1}{print $0}' FS=, OFS=, file.csv

Output:

1,1,1,
2,1,1,
3,1,1,
4,1,1,
5,,,
6,,,
7,,,
8,,,

I was expecting the $3=0 expression to be executed and evaluated to true, and being skipped when the first part of the condition ($1<5) is false.

Expected result:

1,0,0,
2,0,0,
3,0,0,
4,0,0,
5,1,,
6,1,,
7,1,,
8,1,,

Extra question: can I actually use the ternary operator and have in it several instructions executed depending on the condition value ? Is it only a bad practice or actually impossible ?

like image 473
gryyk Avatar asked Sep 07 '25 03:09

gryyk


1 Answers

1st solution: You should have like this code, written and tested with your shown samples and attempts. I have used ternary operators to check if value of 1st field is lesser than 5 or not and based on that setting values for 2nd and 3rd fields here.

awk '
BEGIN { FS=OFS="," }
FNR==1{
  print
  next
}
{
  $2=($1<5?0:$1)
  $3=($1<5?0:$3)
}
1
'  Input_file


2nd solution(Generic approach): If you have to pass N number of fields to be checked in program then better create a function and do the checks and assignment there, using again ternary operators here for computation.

Where:

  • threshold is an awk variable which is assigned to 5 value by which you want to do comparison fir 1st field.
  • fieldCompare is again an awk variable which contains 1 in this case since we want to compare 1st field value to 5 here.
  • checkValue is function where field numbers(eg: 2 and 3 in this case) are being passed with comma separated values to be checked in a single shot within function.
awk -v threshold="5" -v fieldCompare="1" '
function checkValue(fields){
  num=split(fields,arr,",")
  for(i=1;i<=num;i++){
    fieldNum = arr[i]
    $fieldNum = ($fieldCompare<threshold?0:$fieldNum)
  }
}
BEGIN { FS=OFS="," }
FNR==1{
  print
  next
}
checkValue("2,3")
1
'  Input_file
like image 192
RavinderSingh13 Avatar answered Sep 11 '25 02:09

RavinderSingh13