I'm trying to update a text file via sed/awk, after a lot of searching I still can't find a code snippet that I can get to work.
Brief overview:
I have user input a line to a variable, I then find a specific value in this line 10th field in this case. After asking for new input and doing some arithmetic I'd like to replace the 10th field on the 4th line(assuming user chose 4) in the input file.
Any ideas? Thanks in advance
Sample input and expected output will help us to help you...
--ahamed
Update the mileage on a bike
assume line 4 is:
2005:Suzuki:GS500f:Blue:6500:6000:6500:6500:6500:7000
I've extracted the 10th field of the 4th line i.e. 7000.
User enters 12000 (new odometer reading)
If the difference is greater than 4000 (scheduled maintenance), I need to "service" the bike and update the mileage.
Replace 4th line, 10th field with new odometer reading
2005:Suzuki:GS500f:Blue:6500:6000:6500:6500:6500:12000
Try this...
awk -F: '{if($0~bike&&new_mileage-$10>=4000){$10=new_mileage}}1' bike=Suzuki new_mileage=12000 OFS=":" input_file
or
#!/bin/bash
read -p "Which bike ? : " bike
read -p "Enter new mileage : " new_mileage
old_mileage=$( sed "/$bike/{s/.*:\([0-9]*\)$/\1/g}" input_file )
((diff=new_mileage-old_mileage))
if [ $diff -ge 4000 ]
then
sed "/$bike/{s/$old_mileage$/$new_mileage/g}" input_file
fi
Use -i option with sed to make the changes inline i.e. directly
--ahamed
I have a large number of these not specific to values, so I was hoping to replace $# rather than specific values.
Also wouldn't the sed replace all the values? Thanks for the -i that might be what I was missing
#prob pipe was not needed but I ccouldn't get the syntax, revisiting later
old_mileage=$(awk -F':' '{print $10}' motorcycles.txt | awk -v line=$1 'FNR==line')
routine_maint=$(awk -F':' '{print $6}' motorcycles.txt | awk -v line=$1 'FNR==line')
(( difference=current_mileage-old_mileage ))
if [ "$difference" -ge "$routine_maint" ]; then
echo "Overdue"
#do stuff here ie maintenance
else
echo "else"
fi
But I have 5 different function i.e. front tire, rear tire, chain, etc and I'm hoping to just change the $# to update for the specific function
You can replace with sed also but it might get difficult to form the regex. AWK will be pretty easy!
--ahamed
---------- Post updated at 02:16 PM ---------- Previous update was at 02:05 PM ----------
old_mileage=$( awk -F':' 'FNR==line{print $10}' line=$1 motorcycles.txt )
routine_maint=$( awk -F':' 'FNR==line{print $6}' line=$1 motorcycles.txt )
You don't need 2 awk in your code.
--ahamed
awk -F: '{if($0~bike&&new_mileage-$10>=4000){$10=new_mileage}}1' bike=Suzuki new_mileage=12000 OFS=":" input_file
I could change this to awk -F: 'if{(FNR==linenum){$10=new_mileage}}1' linenum=$linenum new_mileage=$new_mileage OFS":" input_file, correct?
Quick question, the 1 following the $10=new_mileage, what's its purpose?
awk -F: 'FNR==linenum{if(new_mileage-$10>=4000)$10=new_mileage}1' linenum=$linenum new_mileage=$new_mileage OFS":" input_file
1 => is for printing the output.
--ahamed
I tried using the exact code above and got an error could not find file OFS etc before attempting to modify it to work for my particular case.
awk: cmd. line:1: fatal cannot open file `OFS`: for reading (No such file or directory)
I already have the action in a conditional statement, so I just need to modify the data on the variable line number in the 10th field and have this written to the file, not just displayed on screen.
if [ "$rout_difference" -ge "$routine_maint" ]; then
echo "Routine maintenance is required on this bike"
echo "Would you like to perform this maintenance and update your records?"
echo "Please enter Yes to confirm, [RETURN] to skip"
read confirm_routine
if [ "$confirm_routine" == "Yes" -o "yes" -o "YES" ]; then
echo "Updating routine maintenance record"
awk -F: 'FNR==linenum{$10=new_mileage}1' linenum=$1 new_mileage=$current_new_mileage OFS":" motorcycles.txt
fi
A bug... try this...
awk -F: 'FNR==linenum{if(new_mileage-$10>=4000)$10=new_mileage}1' linenum=$linenum new_mileage=$new_mileage OFS=":" input_file
--ahamed
Still no luck.
ex record in file:
2005:Suzuki:GS500f:Blue:6500:4000:6500:6500:6500:6500
commands runs but does not update
root@bt:/tmp# cat input_file
2005:Suzuki:GS500f:Blue:6500:4000:6500:6500:6500:6500
root@bt:/tmp# awk -F: 'FNR==linenum{if(new_mileage-$10>=4000)$10=new_mileage}1' linenum=1 new_mileage=12000 OFS=":" input_file
2005:Suzuki:GS500f:Blue:6500:4000:6500:6500:6500:12000
--ahamed
It displays correctly but does not update the file
It will not... You have to redirect the output to a temp file and then rename it...
awk '{...}' file > temp_file
mv -f temp_file file
--ahamed
And that's the piece I've been missing, sorry for being such a pain