views:

59

answers:

4

Hi All, I've used regex's in sed before and used a bit of awk, but am unsure of the exact syntax I need here...

I want to do something like:

sed -i 's/restartfreq\([\s]\)*\([0-9]\)*/restartfreq\1$((\2/2))/2/g' \
    my_file.conf

where the second match is divided by 2 and then put back in the inline edit.

I've read though that sed can't do math.

Can I do this cleanly with sed or awk alone? Suggestions please.

Edit 1
I thought the meaning of my inquiry was straightforward enough, but I guess I might not have given a good enough sample of the data I want to modify. Here's and example of the line in my *.conf file I want to edit inline:

restartfreq        1250    ;# 2500steps = every 1.25 ps

I've posted a solution below. Both of the answers I received were with regards to printing text to the terminal, not editing a file inline. I try to avoid answering my own question, but in this case neither of the answers I received really did what I requested (edit the file, not just print the edited line) and they were substantially longer than my solution and/or required additional linux programs besides just awk or sed.

I do appreciate the help and feedback, though! :)

NOTE: As my usual disclaimer, this is not a homework question, I am a chemical engineering researcher.

A: 

This may be along the lines of what you're looking for:

$ echo 'restart 4' | awk '{$2=$2/2; print}'
restart 2
Dennis Williamson
Yes but can you make that inline edit, if the restart line is in the file? Note the -i on my sed command. P.S. Thanks for the help, you always give good responses to my questions!!
Jason R. Mick
@Jason: I would suggest that you use a temporary file as ghostdog74 shows.
Dennis Williamson
A: 
$ cat script.awk
/restartfreq *[0-9]+/{
    $2 = $2/2
}
{print}
$ awk -f script.awk my_file.conf

If you always want the number to be an integer, change $2/2 to int($2/2).


To overwrite the file, you could either use sponge (if you have moreutils available) or a temporary file.

The latter should be self-explanatory.
Sponge lets you do:

$ awk -f script.awk my_file.conf | sponge my_file.conf
jamessan
I'm inside a bash script. Should I try to nest your awk script? Also, if I'm not mistaken, that just prints the values, it doesn't edit the file inline ... note the "-i" option on my sed command. I need to actually find the line in my file using the regex, divide the number by two and then have that modification *written* to the file. Thanks!
Jason R. Mick
A: 

The following solution actually edits the file inline, only uses one command, and is a bit more elegant than the other proposed solutions (IMHO).

awk '{gsub(/restartfreq\s*[0-9]+/,$2/2,$2)}' my_file.conf

Apologies to Dennis, et. al for answering my own question, but I feel this is the best solution and hopefully it will benefit others who read this...

Edit 1

Whoops I lied. That just prints to the terminal too...

It took me a long time to find, but this works, using only sed and awk:

sed -i '/restartfreq/s/'`sed -n 's/restartfreq*/&/p' my_file.conf | awk '{print $2}'`'/'`sed -n 's/restartfreq*/&/p' my_file.conf | awk '{print $2/2}'`'/g' my_file.conf

Perhaps this can be streamlined, but at least it works! :)

Jason R. Mick
are you sure your final answer works ?
ghostdog74
I would *very highly* recommend that you use a temp file instead of **that**!
Dennis Williamson
@ Ghostdog74, yes, double checked. The only thing undesirable is that I would like to use a ceiling function to make sure the number rounds up.
Jason R. Mick
+1  A: 

this is how you do it with awk only

 awk '$1=="restartfreq"{$2=$2/2;}1' file > t && mv t file
ghostdog74
nice, shorter than my solution, considerably! :)
Jason R. Mick