Use of the ternary operator, an awk example.
Post first published in nixtip
Use of the ternary operator, an
Ok, suppose this source file:
Our mission will be to get a formatted output
port:state:service like this
… and so on …
All closed ports should be marked as
1 the rest will be
Like always, in
*nix system we have plenty of tools (and approaches) to get the expected result, lets try the
At first sight we can identify three fields in our input file and tree tasks be solved.
- Get rid of the slash +
tcpstring of the first field.
- Change the value of the second field for
- Field separator should be
A simply text replacing, is a straightforward way to get the expected result:
Here’s the internals:
We look for a string started by as slash (note de escape char
\/) followed by any number of any character (dot + star
.*) ,followed by the string
closedand ended by any number of space chars
*and replace it with
:1:.For the first line:
21/tcp closed ftpwill be replace for
Same thing for “open” in this case “:0:” will be the substitution string , example:
22/tcp open sshwill be replace for
Our initial tasks get solved ,but we can refine our efforts.
Let’s use the conditional operator.
expr ? action1 : action2
Its pretty straight forward : if
acction1 is performed/evaluated , if not
For our example , field two must change to
1 if it’s value is
closed, if not it should be
The needed conditional operator:
$2=="closed" ? "1" : "0"
Depending of second field value, our program will perform a different action, in this case its returning a string :
At this point, a variable is needed to store it:
n= $2=="closed" ? "1" : "0"
Finally we perform the text substitution:
Note that we reduce the calls to the sub function to just one.
A final (and total different) approach , field substitution instead of text replacing.
Remember our tasks:
a) Get rid of the slash+
tcp string of the first field.
b) Change the value of the second field for
c) Field separator should be
Our input file has naturally three fields (by the default
It’s clear that we can think in a four fields based line, if we add the slash
/ to our field separators by using a
FS='( *)|(/)' where
( *) represents any number of spaces as separator and
(/) represents the slash:
Note that the Output Field Separator
OFS is changed to
> for clarify.
Now, we want to get rid of the second field, technically is not possible, but we can assign the null value (empty string) to it:
Attention, the use of the
awk will print the input line if the result of applying the inner statements to the current input line is true.
$2="" is not an action statement but we force a true return by placing
1 at the end of the program.
If we set the OFS to null value:
We’re close to or goal, the last step is to process the third field:
$3=="closed" ? ":1:" : ":0:"
Like we saw before we need to assign it to a variable,… look the trick:
$3= $3=="closed" ? ":1:" : ":0:"
We say , hey! change `$3 depending of its previous value. So :
A final optimization, the conditional operator performs always an action that imply the print statement, so:
Is equivalent to:
We’re done.comments powered by Disqus