Devigili Devigili - 2 months ago 12
Bash Question

Want to switch 2 values based on order using awk

I'm pretty unfamiliar with awk/sed/grep and have been working to find a solution to a problem. I have a BIOS config file that looks like this..

...

Dual Boot Order #1=0001

Dual Boot Order #2=0002

Dual Boot Order #3=0003

...

Dual Boot Order #15=000E

...


What I want to do is detect if a certain value is in the #1 position, and if it isn't, find it later on in the boot order list and switch it with whatever value is currently in the #1 spot. For example if I wanted to prioritize the 000E boot option, I want my output to be..

...

Dual Boot Order #1=000E

Dual Boot Order #2=0002

Dual Boot Order #3=0003

...

Dual Boot Order #15=0001

...


I am currently storing the value in the #1 in a shell variable and am planning on checking it and basing the next commands on the value of that.

temp=$(awk '/Dual Boot Order #1=..../ { if ( $4 != "#1=000E" ) print $4 }' file.txt)


I'll also need to save these changes afterwards. Anyone know a more straightforward way of accomplishing this? Thanks!

Answer

Let's start with this test file:

$ cat configfile 
...
Dual Boot Order #1=0001
Dual Boot Order #2=0002
Dual Boot Order #3=0003
...
Dual Boot Order #15=000E
...

Now, if we want to swap 000E into first place:

$ awk -v x=000E '$4~x {sub(/=.*/, a, $4)} $4~/#1=/{a=$4; sub(/^[^=]*/, "", a); $4="#1="x} 1' configfile
...
Dual Boot Order #1=000E
Dual Boot Order #2=0002
Dual Boot Order #3=0003
...
Dual Boot Order #15=0001
...

If you have GNU awk (gawk) and you want to change the file in-place:

gawk -i inplace -v x=000E '$4~x {sub(/=.*/, a, $4)} $4~/#1=/{a=$4; sub(/^[^=]*/, "", a); $4="#1="x} 1' configfile

How it works

  • -v x=000E

    This defines an awk variable x with the value 000E.

  • $4~x {sub(/=.*/, a, $4)}

    If the fourth field is a regex match to x, then update it to a (the value saved from #1).

  • $4~/#1=/{a=$4; sub(/^[^=]*/, "", a); $4="#1="x}

    If the fourth field is for #1, then (a) save its current value to a and (b) update its value to x.

  • 1

    This is awk's cryptic shorthand for print-the-line.