Replacing specific entry using sed

Hi guys, I'm new to bash programming, so please pardon me.

I'm trying to replace an entry's text in Books.txt

This code works perfectly:

sed -i "s/$BookTitle/$NewBookTitle/g" Books.txt

But problem is, if there are double entries, it will also replace that entry. For example:

Books.txt
Fondue:Grass <-- intended text to replace (Fondue)
Fondue:Hello

After that code, it becomes:
Elephant:Grass
Elephant:Hello <-- not supposed to change this entry

I only want to change Fondue:Grass to Elephant:Grass. Please help!

Please remove 'g' at the end of your sed command.
g means globally. The change will effect to all entries.
If you remove g , it will change first occurence.

1 Like

try:

sed -i '0,/Fondue/s//Elephant/' Books.txt
1 Like

Thanks karumudi7 and rdrtx1!

---------- Post updated at 08:36 AM ---------- Previous update was at 07:54 AM ----------

Oh, actually, I want to use sed to find the specific line that fulfills the requirement of $BookTitle:$BookAuthor. So if I were to update the value of $BookAuthor, it must update according to the $BookTitle.

E.g.
The Book Author is J.K. Rowling
There are various books by J.K. Rowling:
Philosopher's Stone:J.K. Rowling
Chamber of Secrets:J.K. Rowling
Prisoner of Azkaban:J.K. Rowling

The code below only takes the first entry "Philosopher's Stone:J.K. Rowling" and replaces it with the new author.

sed -i '0,/$BookAuthor/s//$NewBookAuthor/' Books.txt

So it changes Philosopher's Stone:J.K. Rowling to Philosopher's Stone:Candace

However, I want to be able to update $BookAuthor based on the value of $BookTitle.

For example, I want to be able to change Chamber of Secrets:J.K. Rowling to Chamber of Secrets:Candace.

The example below will allow you to change the "BookAuthor" to the "NewBookAuthor" based on the Book Title:

$ cat Books.txt
Philosopher's Stone:J.K. Rowling
Chamber of Secrets:J.K. Rowling
Prisoner of Azkaban:J.K. Rowling

$ BookTitle="Chamber of Secrets"

$ NewBookAuthor=Candace

$ sed "s/\($BookTitle:\)\(.*\)$/\1$NewBookAuthor/g" Books.txt
Philosopher's Stone:J.K. Rowling
Chamber of Secrets:Candace
Prisoner of Azkaban:J.K. Rowling
1 Like

Use sed 's address capability to find the line and then replace old author with new:

$ sed "/$BookTitle/s:$BookAuthor:$NewBookAuthor:" Books.txt

@karumudi7: g means all occurrencies in that respective line, NOT in entire file!

1 Like

Okay, I think I should specify my question further.

I need to be able to update the values of a specific value in my .txt file.

For example: [fruit]:[brand]:[price]:[qty]
apple:greenwood:0.70:50
pear:sunshine:0.95:60
dragonfruit:moonshine:1.50:50

If I do a search for apple and greenwood, I should be able to update the fruit, brand, price, and qty of that entry. So lets say I did a search (fruit & brand) on pear & sunshine. I'll be able to update the value of pear, sunshine, price, and quantity.

echo -n "Fruit : "
	read Fruit
	echo ""
	echo -n "Brand : "
	read Brand
	echo ""
	if grep -q "$Fruit:$Brand" "Fruit.txt"; then
		echo "Fruit found!"
		echo ""
		selection=""
		until [ "$selection" == "e" ]; do
			echo "a) Update Fruit Name"
			echo "b) Update Brand"
			echo "c) Update Price"
			echo "d) Update Qty"
			echo "e) Back to main menu"
			echo ""
			echo -n "Please enter your choice: "
			read selection
			echo ""
			case $selection in
				a)
					echo -n "New Fruit Name : "
					read NewFruit
					echo ""
					sed -i "0,/$Fruit/s//$NewFruit/" Fruit.txt
					echo "Fruit Name has been changed from $Fruit to $NewFruit."
					Fruit="$NewFruit"
					echo ""
					;;

This is what I've done so far, but as per my problem above, I'm unable to update specific values in a specific entry.

Fruit & Brand variables will remain as constants to match with the .txt file.

I'm figuring there will be 4 different codes for the updating of 1) fruit, 2) brand, 3) price and 4) qty. Sed is confusing me with all the pattern flags and command line options.

P.S.: I tried using grep from my .txt source, and pipe it into a do-while loop, but I'm still unable to update the specific values.

From pottery to green stuff - interesting. However, including solutions to others of your threads, try

$ F=apple
$ B=greenwood
$ OP=0.70
$ NP=1.20
$ sed "/$F.*$B/ s/$OP/$NP/" file
apple:greenwood:1.20:50
pear:sunshine:0.95:60
dragonfruit:moonshine:1.50:50

sed is extremely powerful, so taking your time sitting back and learning it is invaluable.

If you want to replace specific field values then I recommend using awk instead of sed :

awk -F: -v oldfruit="apple" -v newfruit="orange" '$1==oldfruit{$1=newfruit}1' Fruits.txt

In above program I am using colon : as field separator and changing the value of specific field, 1st field $1

Be careful - this will replace ALL apples with oranges, not only greenwood's!

Oh, here is the modified program:

awk -F: -v oldfruit="apple" -v newfruit="orange" -v brand="greenwood" '$1==oldfruit&&$2==brand{$1=newfruit}1' OFS=: Fruits.txt

RudiC, thanks for pointing that out.

Hello Guys ,

I am new to shell scripting.

Below is what i have for you guys

file name employee.txt where I have a ^M at the end of the file , i can remove ^M usind sed

Solution 1Example 1 :

sed 's/ ^M/ /gi' employee.txt

Solution 2 Example 2 : :

1,$s/ ^M/ /g

But here is a catch on 1 thing ,where we need to apply the same concept to a entire folder where we have more than 50 file having the same problem of ^M to be removed , how can we do that ?

Problem :

ls -lrt /root/sunny1/
                              
                               
-rw-r--r-- 1 root root  3325 Dec  7  2011 install.log.syslog
-rw-r--r-- 1 root root 26725 Dec  7  2011 install.log
-rw------- 1 root root   949 Dec  7  2011 anaconda-ks.cfg
-rw-r--r-- 1 root root  1071 Oct 30 20:13 emplst.sh
drwxr-xr-x 2 root root  4096 Dec 10 20:51 Desktop
-rw-r--r-- 1 root root  1669 Jan 10 17:53 natasha_access.sh
-rw-r--r-- 1 root root   108 Jan 10 17:54 natasha_others
-rw-r--r-- 1 root root   109 Jan 10 17:56 last_sasha.sh
-rw-r--r-- 1 root root   140 Jan 10 18:02 emplsts_1_4.sh
drwxr-xr-x 2 root root  4096 Jan 10 18:33 redhat
-rw-r--r-- 1 root root   812 Jan 10 18:37 emplsts.sh
-rw-r--r-- 1 root root    59 Jan 14 18:52 emp1.sh
-rw-r--r-- 1 root root   549 Jan 19 12:55 employee.txt
-rw-r--r-- 1 root root   549 Jan 19 13:14 n_employee.txt
-rw-r--r-- 1 root root   507 Jan 19 13:20 f_employee.txt
[root@localhost ~]#

@sunnyd1: Please start a new thread with your question..