I have a file like a database where I save name,surname,date of birth, gift, and I want to know if this person have got a gift from us or not. Those dates are splited by tabs in the file, one person per line, like:

name1  surname1  dateofbirth1  gift1
name2  surname2  dateofbirth2  gift2

Inside gift colum, I save "Yes" or "No" and my code looks like:

while IFS=$'\t' read -r name surname dob gift; do
    if [[ "$gift" == "No" ]]; then
        echo "Congrats, here is your gift
done < "file.txt"

But the gift colum, don't seems to change to yes, only seems to be there as an aux var. How can I change the value of that line, in that colum, to yes?

  • 1. Is gift actually set as yes in your file? 2. Did you create the file.txt on Windows but are running the code on a Linux platform? – roaima Apr 7 at 16:11
  • By default, gift is set as No. So inside the loop, I want to check those ones who have No and change it to yes. And no, file it's made on Linux (Ubuntu). – Multi Apr 7 at 16:15
  • 2
    @Multi17 The simple act of read-ing a line does not bind that line to the variables you specified for receiving the line’s fields. You need to rewrite that line with the updated value of "${gift}". As to how do that, replacing it ”in-place” (i.e. on the same file and line as your source file.txt) cannot be done simply. What you may do in a simple way is just output the updated line, along with all the other lines, and redirect that output to another file, which you’ll then move to file.txt to replace the original file. – LL3 Apr 7 at 16:20
  • @LL3 Okey, thanks for explain this. I will give it a go to it! – Multi Apr 7 at 16:21

Reading a value from a file and then changing the variable that holds that value will not change the value in the file.

Instead, you would have to detect what values need changing, change them, and then output the complete file (including modified values) to a new file. This new file can then be moved to the original name, replacing the old file.

Also, parsing text in the shell is generally to be avoided. Instead, consider using something like awk for that:

awk -F '\t' 'BEGIN { OFS=FS }
             $4 == "No" { print "Congrats, here is your gift" >"/dev/stderr" }
             { $4 = "Yes"; print }' file.txt >newfile.txt

This would read through the file line by line and whenever the fourth column says No, it outputs the text Congrats, here is your gift.

Then, for every line, the fourth column is unconditionally set to Yes before the whole line is printed.

The way the program is written and run above, the Congrats... message will appear in the terminal (it's written to the standard error stream) while the updated contents of the file will be written to the new file called newfile.txt.

The BEGIN block at the start of the code simply sets the output field separator, OFS, to the same value as the input field separator, FS, which is set to a tab character on the command line using -F '\t'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.