4

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

1
  • I'd also like to account for future changes to the text input file. If for example, a line is removed or added, and the number of matching lines increases or decreases. Commented Aug 14, 2018 at 17:55

3 Answers 3

3

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
Sign up to request clarification or add additional context in comments.

2 Comments

This works well for my purpose. It accounts for changes to the input. For example, with adding a filed "THIS_MINOR2=1, or commenting out THIS_BUILD=491, it still prints the version number as expected. Thank you.
(output=="")? output=$2 : output=output"."$2 is written more concisely as output = (output=="" ? "" : output".") $2
1

paste is for this

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

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.