2

Given a file input.txt with contents:

xyMnZnMs76XHgsWJ
size: YN3hxFqFeUxXUMrQ
USPqYEnbquwFhUW7
vhJJduHZu25qHzTw
size: JaTDhQYQtLRWBLjj
uE5HGDAZN6DHU73Q
QxVPfQQaKTgR9LXQ
grnsm8bwSz5fJbQS size:
7CcuZxCHSJYhcdqg
ZuWadAaLWFwDwj5Z

how to use if (condition) {...} else {...}?

I tried to use:

awk -F ':' '
IF ($1 ~ /size/) {
    print "match: "$0;
} ELSE {
    print "non-match: "$0;
}' input.txt

but all lines are matched (even ones without $1 containing "size"):

match: xyMnZnMs76XHgsWJ
match: size: YN3hxFqFeUxXUMrQ
match: USPqYEnbquwFhUW7
match: vhJJduHZu25qHzTw
match: size: JaTDhQYQtLRWBLjj
match: uE5HGDAZN6DHU73Q
match: QxVPfQQaKTgR9LXQ
match: grnsm8bwSz5fJbQS size:
match: 7CcuZxCHSJYhcdqg
match: ZuWadAaLWFwDwj5Z

I expect the output to be:

non-match: xyMnZnMs76XHgsWJ
match: size: YN3hxFqFeUxXUMrQ
non-match: USPqYEnbquwFhUW7
non-match: vhJJduHZu25qHzTw
match: size: JaTDhQYQtLRWBLjj
non-match: uE5HGDAZN6DHU73Q
non-match: QxVPfQQaKTgR9LXQ
non-match: grnsm8bwSz5fJbQS size:
non-match: 7CcuZxCHSJYhcdqg
non-match: ZuWadAaLWFwDwj5Z
1
  • Are you only interested in Awk answers, or other languages as well (sed, Perl, Python, Ruby, Raku, etc.)? You might find an answer in another language that strikes a chord with you. Commented Oct 15, 2023 at 19:24

3 Answers 3

14

Let's explain.

The syntax structure for awk is « pattern { action } », where either component (but not both together) is optional. When you wrote IF ($1 ~ /size/) { print "match: "$0; } you were not using the if keyword, but were actually concatenating an empty string (the unset variable IF) and an expression ($1 ~ /size/) that evaluates to either 0 or 1. Because of the string concatenation the result is considered to be a string ("0" or "1") and is "true" if it has non-zero length. Either result has a length so the pattern condition is considered unconditionally true. At this point the { action } is triggered and you get print "match: "$0 executed.

Let's fix.

Reading the documentation for awk (see man awk) you'll find that the ifelse structure is in lower case. Furthermore, you can't use such a structure except inside the « { action } » part of each statement.

awk -F: '
    { if ($1 ~ /size/) { print "match:", $0 } else { print "non-match:", $0 } }
' input.txt

However, notice that your line grnsm8bwSz5fJbQS size: is treated as a non-match in your required output but in this code it's output as a match. This is because the Regular Expression /size/ matches the first colon-separated field, grnsm8bwSz5fJbQS size. You would need to identify the start and end of the string for a precise match - but better would be to compare as a literal string:

awk -F: '
    { if ($1 == "size") { print "match:", $0 } else { print "non-match:", $0 } }
' input.txt

Or,

awk -F: '
    $1 != "size" { print "non-match:", $0 }
    $1 == "size" { print "match:", $0 }
' input.txt

Or even,

awk -F: '
    $1 != "size" { printf "non-" }
    { print "match:", $0 }
' input.txt
3
  • 3
    Had they used if (properly in lowercase), that would have given a syntax error. Which might not explain the pattern/action -syntax and having to put the statement inside braces, but would in a way be a bit more descriptibe...
    – ilkkachu
    Commented Oct 13, 2023 at 9:27
  • re that last one, you could also do awk -F: '{ print(($1 != "size" ? "non-" : "") "match", $0) }' input.txt or so if you're going to golf it...
    – ilkkachu
    Commented Oct 13, 2023 at 9:29
  • 1
    @magor I'm trying to work out what your comment is driving at. Do you feel there is something wrong with my answer? Commented Oct 13, 2023 at 10:52
2

For that I wouldn't even use a if-statement, they are for more complicated stuff. You could just use do this:

awk -F':' '/^size/ {print "match: " $0} !/^size/ {print "non-match: " $0}' input.txt

or my preferred way is to do it with a variable called pat, so you can change it later more easily:

awk -v pat="size" -F':'  '$1~pat {print "match: " $0}; $1!~pat {print "non-match: " $0}' input.txt
0
1

This works for me:
awk -F: '{if ($1 =="size") {print "match: "$0} else {print "non-match: "$0}}'

With awk, you always have to use curly braces for the code, like :

awk '{ your code }'

Also the if/else is not with capital letters.
You can find some further examples here.

1
  • The pattern part can include code: the only restriction is that it must be constitute an expression resulting in a boolean value, and not contain braces. It can include a built-in function like match() or index(), or gsub ("\047", "\047") % 2 to select lines with mismatched single quotes, or even call user-defined function like isPrime( $1 + $2), or mess with the input like $0 = sprintf("Wrap %s Done", $0), or assign variables like (j = (NR <=3 ? "Now" : "Later" )). Commented Oct 13, 2023 at 14:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .