0

I am trying to remove lines from a text file from a Bash Script using command sed.

Here is how this function works.
User enters record number Program Searches for record number Program deletes record

Here is my code:

r=$(grep -h "$record"  student_records.txt|cut -d"," -f1)  #find the record that needs to be deleted
echo $line -->> This proves that previous command works
sed -i '/^$r/d' student_records.txt  -->> this does not work

Any ideas?

1
  • They are unique records. Commented Oct 31, 2014 at 4:36

1 Answer 1

1

To remove a line containing $record from the file:

grep -v "$record" student_records.txt >delete.me && mv -f delete.me student_records.txt

In the above, $record is treated as a regular expression. This means, for example, that a period is a wildcard. If that is unwanted, add the -F option to grep to specify that $record is to be treated as a fixed string.

Comments

Consider these two line:

r=$(grep -h "$record"  student_records.txt|cut -d"," -f1)  #find the record that needs to be deleted
echo $line -->> This proves that previous command works

The first line defines a shell variable r. The second line prints the shell variable line, a variable which was unaffected by the previous command. Consequently, the second line is not a successful test on the first.

sed -i '/^$r/d' student_records.txt  -->> this does not work

Obseve that the expression $r appears inside single-quotes. The shell does not alter any inside single quotes. Consequently, $r will remain a dollar sign followed by an r. Since a dollar sign matches the end of a line, this expression will match nothing. The following would work better:

sed -i "/^$r/d" student_records.txt

Unlike the grep command, however, the above sed command is potentially dangerous. It would be easy to construct a value of r that would cause sed to do surprising things. So, don't use this approach unless you trust the process by which you obtained r.

What if more than one line matches record?

If there is more than one line that matches record, then the following would generate an unterminated address regex error from sed:

r=$(grep -h "$record"  student_records.txt|cut -d"," -f1)
sed -i "/^$r/d" student_records.txt

This error is an example of the surprising results that can happen when a shell variable is expanded into a sed command.

By contrast, this approach would remove all matching lines:

grep -v "$record" student_records.txt >delete.me && mv -f delete.me student_records.txt
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks John for the clarification!
You should perhaps also point out the obvious sed -i "/^$record,/d" student_records.txt
@tripleee Good point. I added that command along with a discussion of the security issues associated with it.
Using grep to obtain $r from $record is rather roundabout, still.
@tripleee Very true. My proposed solution was just to look for $record and delete that line via grep. This makes unnecessary the creation of r. (The same direct approach could be done with sed -i.)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.