Beyond Ocean
Beyond Ocean

Reputation: 45

how to write a linux shell variable to a file's given line?

I tried to Realize the function shown as the below FAKE code: to compute the net down rate and update the net log. May somebody show me the right code? Thanks.

    #!/bin/bash
    #check_net.sh

    net_link_error_total=33
    net_link_ok_total=55
    save_link_rate()
    {
        sed -i  '1 cnet_link_error_total=$net_link_error_total' yy.log
        sed -i  '2 cnet_link_ok_total=$net_link_ok_total' yy.log

        net_link_ok_rate=net_link_ok_total/(net_link_ok_total+net_link_error_total) * 100%
        sed -e "3c  net_link_ok_rate= /$net_link_ok_rate" yy.log    
    }

    save_link_rate

After I executed sed -i '2 cnet_link_ok_total=$net_link_ok_total' yy.log

Upvotes: 0

Views: 72

Answers (3)

muru
muru

Reputation: 4887

If you have GNU awk with the in-place module (versions 4.1.0 and above), then:

awk -i inplace -v error=$net_link_error_total -v ok=$net_link_ok_total \
    'NR == 1 {$0 = "net_link_error_total=" error}
     NR == 2 {$0 = "net_link_ok_total=" ok}
     NR == 3 {$0 = "net_link_ok_rate=" (ok + error)*100/ok}
     1' yy.log

$0 is the current line, and NR the line number, so I set each matching line to the required string.

If the field names are already in the file in those lines, you can simplify it further, but setting the field instead of the whole line:

awk -i inplace -F= -v error=$net_link_error_total -v ok=$net_link_ok_total \
    'NR == 1 {$2 = error}
     NR == 2 {$2 = ok}
     NR == 3 {$2 = (ok + error)*100/ok}
     1' yy.log

Upvotes: 0

SLePort
SLePort

Reputation: 15461

In the first two sed commands, variables are not expanded within single quotes.

Your last command applied to third line will works as intended but it's a good practice to restrict expansion to only variables, and not to enclose whole sed command within double quotes. Moreover I would add a space after each sed c commands for readability:

sed -i  '1c net_link_error_total='"$net_link_error_total"'' yy.log
sed -i  '2c net_link_ok_total='"$net_link_ok_total"'' yy.log

sed -e '3c net_link_ok_rate= /'"$net_link_ok_rate"'' yy.log

Also your rate calculation is wrong. You can use bc for this:

net_link_ok_rate=$( echo "scale=2; $net_link_ok_total/($net_link_ok_total+$net_link_error_total) * 100" | bc) 

Finally, note that with your last sed command the file will not be edited in place, as the -i flag is missing.

Upvotes: 1

abuccts
abuccts

Reputation: 339

Use double quotes instead of single quotes, because single quotes limit substitution of variables. In your case, what you want is:

sed -i "1 cnet_link_error_total=$net_link_error_total" yy.log
sed -i "2 cnet_link_ok_total=$net_link_ok_total" yy.log

If you want to do a float division in bash, you should use a tool such as bc. In your case, for example:

ok_rate=$(echo "scale=2; $ok_total/$((ok_total+error_total))" | bc)

Upvotes: 0

Related Questions