Mistake with sed espression is saving part of pattern
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Mistake with sed espression is saving part of pattern
Hi all,
got a textfile with : as delimiters in between fields. e.g.
1:2:3:4:5:6
Thomas Cruise:Johnavid:Peter:Betty:Jane
The names may or may not contain white spaces.
I am required to substitute any one of these names in the file with a new one inputted by user.
e.g. to change John to Johnny, David to Beckham, etc. without touching any of the other names in the same line. Just one at a time.
So here's the sed expression I was trying out with:
sed -i "s/<\(.:.:\)David>/$\1Beckham/" names.txt
I also tried:
sed -i "s/<\(.*\)David>/<\1Beckham>/" names.txt
All to no avail. No error mistake, just nothing gets substituted. I am really lost and seem to be missing some crucial concept.
I can only get the first field, which is Thomas Cruise, to sub. It will be very helpful if someone can also explain why there are $ and < > in the 2nd half of the sed expression ie. the new words to sub in.
1:2:3:4:5:6
Thomas Cruise:Johnavid:Peter:Betty:Jane
sed -i "s/<\(.:.:\)David>/$\1Beckham/" names.txt
I also tried:
sed -i "s/<\(.*\)David>/<\1Beckham>/" names.txt
Why do you use the '<' and '>' characters?
Here's first of all a very _simple_ version of a replace statement:
# sed 's/David/Beckham/g' names.txt
to replace each occurence of David with Beckham (g extension)
I'm not sure if that already serves your purpose, but you could possibly use it as a base for your work ... By the way, if it's important for you to update a specific column, maybe awk is a better choice.
Thomas Peters:Thomas Cruise:Thomas Peters:Betty:Jane
Hence I have to use the /( and /( characters, so that I can go specify, for example Thomas Peters in column 3 will get edited to Thomas John or something.
I have to be able to exactly pinpoint which column is being edited, and the rest of the other columns cannot be edited. Only that column.
I used sed because sed is able to directly edit a text file, while awk seems to require a temporary storage which is something that I am reluctant to implement.
-----------------------
Line to edit: 2
Column to edit: 2
New value: Timmy Peter
-----------------------
Code:
Sample file (many lines of such stuff):
Thomas Peters:Thomas Cruise:Thomas Peters:Betty:Jane
Peter:David:John:Peter:Jane
Sample output based on above user input:
Thomas Peters:Thomas Cruise:Thomas Peters:Betty:Jane
Peter:Timmy Peter:John:Peter:Jane
Hence, the shell script will edit Line 2, Column 2 and replace the original David with the new Timmy Peter.
I created a script that shows how you can parse/replace a name from a delimited file. You can use it to glean methods for your own script. Sorry its a little long. Cheers.
What the script does :
- creates a sample delimited text file of names { delimiter = : }
- parses the names to numbered lines and displays to the user
- requests the user choose a name (by line number), and confirms choice
- prompts for a new name, shows old and new names, and confirms
- changes the old name to the new name in the file
- displays the sample file to the user to show the physical changes
#!/bin/sh
#
# fx
#
# --- create a sample text file with data --- #
# set the name of the input file where the substitution will occur
ifile=tx
# the header message for the user
msg='This is a list of names from which one can be chosen for substitution.\
The names are numbered for reference.\
When you have found a name to be changed, remember the number and press the Q key.\n\n'
# start with a fresh sample file
cat /dev/null > $ifile
# set the delimiter
dm=':'
# create a set of names to write into sample file
buf=
for token in 'Joe Thomas' 'Jane Thomas' 'Robert Thomas' 'Myrna Thomas' 'Edward Thomas' 'Gus Sr. Thomas' 'Bud II Thomas'
do
buf="$buf$token:"
done
# write the names to the sample file
echo $buf > $ifile
# show the user the list of names and ask for a choice of the one to be changed
#
# note how the msg is placed before the first numbered line
#
cat $ifile | sed 's/:/\n/g' | cat -b | sed '1s/^\(.*\)$/'"$msg"'\1/' | less
# request the number from the user
echo -e "\033c"
echo 'Enter the number of the name to be changed and press the [ Enter ] key.'
echo -e "Or just press the [ Enter ] key to exit and make no changes.\n"
# parse the old name
oldname=`cat $ifile | sed 's/:/\n/g' | sed $uchoice\!d`
# show the choice and get confirmation from the user
echo -e "\033c"
echo -e "This is your choice : $oldname\n"
echo 'IF this choice is CORRECT and you want to change the name, then enter the NEW NAME and press the [ Enter ] key.'
echo -e "Otherwise if this choice is NOT CORRECT then just press the [ Enter ] key and no changes will be made.\n"
# confirm with user
echo -e "\033c"
echo -e "The OLD NAME to be changed is : $oldname\n"
echo -e "You chose this NEW NAME to replace the old name : $newname\n"
echo 'IF this is correct then press the [ Y ] key, then the [ Enter ] key.'
echo 'IF NOT correct then just press the [ Enter ] key and no changes will be made.'
echo
# get the users choice to proceed or not
read confirmed
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.