replacing field in specific line in a file

Hi,

I know there are lots of threads on replacing text within files, usually using sed or awk. However, I find it hard to adapt examples that I found to my specific case. I am kind of new to UNIX and have hard times learning the syntax either for sed or awk so I would appreciate any help. Here's what I want to do:

I have a file containing user information

PIN000:FirstName.LastName:AccountNumber:Balance

I use cut to retreive Balance and place it into a variable and do calculations with it, but I don't know how to replace the Balance in the file above with new Balance that I get.

For example,
withdrawsum=number
Balance=&(($Balance - $withdrawsum))

then I want to replace the Balance part of the file so that when I exit the script, the changes remain and the next time I try to read Balance from the user file, I get the changed one.

For example,

user file:

PIN123:John.Smith:10203040:1000

so the Balance=1000

lets say that

withdrawsum=10

So once I've done the subtraction from the balance,

Balance=$(($Balance - $withdrawsum))

I want the new balance to be overwritten in the old balance place, so the file would look like this:

PIN123:John.Smith:10203040:980

Any thoughts? Thanks in advance for your help.

The problem is that file I/O has no "insert" operation: If the new data is a different length than the old you need to rewrite everything after the change.

There's way better, faster, and simpler ways than the 'cut' utility to read fields from a data file, but it's difficult to help without seeing the rest of your program. It'd also tell me what other fields from that line you have, since just knowing the balance isn't enough to find and edit that exact line...

1 Like

I would definitely like to hear about these 'better, faster and simpler ways'. As I said, I'm new to UNIX and there are plenty of stuff to learn so any advice would be appreciated. The whole script is ~100 lines, so I probably won't paste it here. But if you like to know what other fields of that line are used for, then here it is:

PIN000 - Three last digits are used as a password for user's account (I use PIN in front so the user's entry is more easily read, though I would like to encrypt this field in the future for security reasons.
FirstName.LastName - Used to identify the user.
AccountNumber - I don't use this one for now, but this is a fixed length number. I plan to use this number for transactions between users within the system.

Basically, it's just a simple script used to manage users' finances in a simple 'deposit' 'withdraw' manner. However, it's very limited as of now, cause all the changes done by the user are not saved into his/her user entry (that line in the file).

Maybe something like this,

wd=10

awk -v wd="$wd" -F: '$NF=$NF-wd' OFS=: file > temp && mv temp file

Try it first on some test files.

1 Like

Here's the basic idea. Instead of creating and waiting for five seperate processes per line, you run read once. It's not even a process, just a builtin -- faster than awk/cut by a factor of 20 or so. And that's just if you're running awk/cut once per loop.

IFS=":" read PIN FIRST LAST ACCT BALANCE < filename

It reads data one line at a time from standard input(or whatever you redirect into standard input) and puts it into shell variables. It splits based on a special variable, IFS, which is usually space, but can be anything you want.

To loop through the whole file, you would do:

while IFS=":" read PIN FIRST LAST ACCT BALANCE
do
        # code to do something with the values here
done < filename

Now say you have a single line that you need to split into variables, but don't want to read it from file. Simple:

read A B C D E F <<< "words words flarg been words more words"

The <<< feeds it that txt on standard input without you having to create a file or pipe.

1 Like

it worked! thanks for the help, people. Just another advantage of using Open-source OS, lots of great people contributing to teaching n00bs :slight_smile: great OS, great community!