4

My file currently has

Name.      Address.   Phone number 
Jack.        L.A             1435672
John         L.A.            1465432
Nick.        F.l.            1489756

When the user wants to delete a contact from the list he enters the name of the contact and the program deletes the whole line. When the user wants to modify a contact he enters the name and find the contact and then change it with a new name, address and phone number. I am trying to achieve this using two functions delete and modify.

pa4080
  • 30,621

1 Answers1

4

You can use the command sed with syntax like as:

sed "/^\t$name/d" in-file

Where:

  • we must use double quotes when inside the regular expression need to pass a shell variable - $name in this case.

  • ^ will match to the beginning of the line.

  • \t will match to a single tab.

  • the command d at the end will delete each line that match to our regexp /^\t$name/.

You can add -i (or -i.bak) to create the changes in place of the file (or and create a backup copy). Or you can Blueirect the output of the command to anotger file, etc.:

sed "/^\t$name/d" in-file -i.bak
sed "/^\t$name/d" in-file > out-file

More examples:

$ name='Blue'                       # assign a value to the shell variable $name

$ cat in-file                       # output the content of the input file
first line
second line
    Blue
    fourth line
Blue

$ sed "/^\t*$name/d" in-file        # remove the lines that begin ^ with 0 or more tabs followed by the value of $name
first line
second line
    fourth line

$ sed -r "/^\t+$name/d" in-file     # remove the lines that begin ^ with 1 or more tabs followed by the value of $name; enable extended regexp -r
first line
second line
    fourth line
Blue

$ sed -r "/^\t{0,1}$name/d" in-file # remove the lines that begin ^ with 0 or 1 tabs followed by the value of $name; enable extended regexp -r
first line
second line
    fourth line

$ sed -r "/^\t?$name/d" in-file     # remove the lines that begin ^ with 0 or 1 tabs followed by the value of $name; enable extended regexp -r
first line
second line
    fourth line

$ sed -r -e "/^(\t|\s|\s\t|\t\s)?$name/d" -e 's/^\t//' in-file # remove the lines that begin ^ with 0 or 1 tabs, or spaces, or spaces and tabs, or tabs and spaces`; remove the tabs in the beginning of the rest lines 
first line
second line
fourth line

Edit: Here is how to substitute a whole line from the example provided in the updated question. Here is used the sed's substitution command s/regexp/replacement/.

First let's assume we have defined the following sets variables:

old_name='Jack.' old_address='L.A.' old_phone='1435672'
new_name='Tom.' new_address='F.l.' new_phone='875632'

If we need exact match of the line and want to keep the exact format, we can use the following command, that uses capture groups option: (...) -> \1, etc.; additionally the option -r (use extended regular expressions) is applied to simply the syntax (check this question as reference):

sed -r "s/^(\t*|\s*)$old_name(\t*|\s*)$old_address(\t*|\s*)$old_phone(\t*|\s*)$/\1$new_name\2$new_address\3$new_phone\4/" in-file

In this way we capturing the field separators (that in this case cold tabs and/or spaces) and output them in their place within the replacement string.

If we do not need to be so accurate we can use something more simple as the follow (where in the place of the capture groups our regex will expect 0 or more * characters of any type .):

sed -r "s/^.*$old_name.*$old_address.*$old_phone.*$/$new_name\t$new_address\t$new_phone/" in-file

Or even more simple:

sed -r "s/^.*$old_name.*$/$new_name\t$new_address\t$new_phone/" in-file

Example:

$ cat in-file 
Name.   Address.  Phone number
Jack.   L.A.      1435672               
John.   L.A.      1465432
Nick.   F.l.      1489756

$ old_name='Jack.' old_address='L.A.' old_phone='1435672' new_name='Tom.' new_address='F.l.' new_phone='875632'

$ sed -r "s/^(\t*|\s*)$old_name(\t*|\s*)$old_address(\t*|\s*)$old_phone(\t*|\s*)$/\1$new_name\2$new_address\3$new_phone\4/" in-file 
Name.   Address.  Phone number
Tom.    F.l.      875632               
John.   L.A.      1465432
Nick.   F.l.      1489756
pa4080
  • 30,621