Chris
Chris

Reputation: 158

How to use awk to parse and print multi line version number from file as dot seperated values on one line

I have a text file (mcafee agent install script named install.sh) that contains many lines, including the following lines that I am interested in:

THIS_MAJOR=5
THIS_MINOR=0
THIS_PATCH=6
THIS_BUILD=491

I want to use awk to print the numbers from column 2 on each line as a dot separated version string on one line so that the output looks like this:

5.0.6.491

I am using the following awk command to match on the lines containing the version numbers in column 2, and to print the value and append the dot character with printf:

awk -F "=" '/^THIS_/ && /MAJOR|MINOR|PATCH|BUILD/ && !/AGENT/ {printf("%s.", $2)}'  /tmp/install.sh

Which prints out:

5.0.6.491.

I'm trying to avoid printing the last '.' character

Here's what I've tried so far

Using gsub to replace the '.' character.
Not ideal, because I should be able to tell awk to just not print the '.' if it's operating on the last line.

awk -F "=" '/^THIS_/ && /MAJOR|MINOR|PATCH|BUILD/ && !/AGENT/ {printf("%s.", $2)} END{gsub(".","",$2)}' /tmp/install.sh

Attempt to use END and not print the last "." :

awk -F "=" '/^THIS_/ && /MAJOR|MINOR|PATCH|BUILD/ && !/AGENT/ {printf("%s.", $2)} END{printf("$s", $2)}' /tmp/install.sh

Which no longer matches correctly on the lines that contain the version numbers.

Attempt to determine number of lines, and while not processing the last line, print the dot character, and on the last line, print without the dot character.

awk -v nlines=$(wc -l < $a) -F "=" '/^THIS_/ && /MAJOR|MINOR|PATCH|BUILD/ && !/AGENT/ {printf("%s.", $2)} NR != nlines { printf("%s", $2)}' $a >> /tmp/install.sh

Which returns:

-bash: $a: ambiguous redirect

How can I get awk to not print the '.' character for the number from the last line?

Thanks

Upvotes: 4

Views: 633

Answers (3)

Ed Morton
Ed Morton

Reputation: 203324

Personally I'd do it like this so the version number that's output is independent of the order the lines that make up the parts of the version number appear in the input and you can trivially modify it to print whatever else is added to the input in any order:

$ awk -F'=' -v OFS='.' 'sub(/^THIS_/,""){v[$1]=$2} END{print v["MAJOR"], v["MINOR"], v["PATCH"], v["BUILD"]}' file
5.0.6.491

Upvotes: 1

karakfa
karakfa

Reputation: 67467

paste is for this

$ awk -F= '/THIS_(MAJOR|MINOR|PATCH|BUILD)/{print $2}' file | paste -sd.
5.0.6.491

Upvotes: 1

zzevannn
zzevannn

Reputation: 3714

Not sure I understand the requirements in the comments, but something like this would work and isn't too far off from what you've tried. You just need to swap to prepending a dot to a match instead of appending it, and skip the first one.

awk -F "=" '/^THIS_/ && /MAJOR|MINOR|PATCH|BUILD/ && !/AGENT/ {(output=="")? output=$2 : output=output"."$2} END {print output}'

Matching is the same, the logic was changed to: {(output=="")? output=$2 : output=output"."$2} END {print output}

Which checks if a variable named output is empty (which it will be on the first match) and then set it to $2 if so, and if not, it appends a . following by the value of $2.

e.g.

$ cat so.txt
sagfdsga
asgasd
asdg
sdag
asg
:wq
234
534215.4361436


i
favorite
I have a text file (mcafee agent install script named install.sh) that contains many lines, including the following lines that I am interested in:

THIS_MAJOR=5
THIS_MINOR=0
THIS_PATCH=6
THIS_BUILD=491

sagfdsga
asgasd
asdg
sdag


$ awk -F "=" '/^THIS_/ && /MAJOR|MINOR|PATCH|BUILD/ && !/AGENT/ {(output=="")? output=$2 : output=output"."$2} END {print output}'  so.txt
5.0.6.491

Upvotes: 3

Related Questions