LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-20-2010, 11:53 AM   #1
zizou86
LQ Newbie
 
Registered: Jan 2010
Posts: 16

Rep: Reputation: 0
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.

Please kindly assist.

Thank you.

Regards.
 
Old 01-20-2010, 12:09 PM   #2
ForzaItalia2006
Member
 
Registered: Dec 2009
Location: Walldorf, Germany
Distribution: (X)Ubuntu, Arch, Gentoo
Posts: 205

Rep: Reputation: 67
Hey,

Quote:
Originally Posted by zizou86 View Post
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.

- Andi -
 
Old 01-20-2010, 12:17 PM   #3
zizou86
LQ Newbie
 
Registered: Jan 2010
Posts: 16

Original Poster
Rep: Reputation: 0
Hi,

Sorry have to explain abit more.

I might have repeated names in one line. e.g.:

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.

THanks for help.
 
Old 01-20-2010, 12:20 PM   #4
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738
Please post a sample of the actual file, and an example of what you want the new output to be.

Go here for a really good SED tuturial:
http://www.grymoire.com/Unix/
 
Old 01-20-2010, 12:25 PM   #5
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian + kde 4 / 5
Posts: 6,837

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
I think I'd reconsider the decision not to use awk. awk handles regularly delimited fields like this much better than sed.

And there are ways to avoid temporary files. You can set it inside a bash script and have the output saved to a temporary variable first, for example.
 
Old 01-20-2010, 12:28 PM   #6
zizou86
LQ Newbie
 
Registered: Jan 2010
Posts: 16

Original Poster
Rep: Reputation: 0
Hi, sorry if its kind of vague.

e.g.

User input -

-----------------------
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.

Thanks.
 
Old 01-20-2010, 12:37 PM   #7
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738
Since you have nice lines and columns, you might be better off with AWK. The site I linked has a good tutorial.

Part of the key to this is deciding if something is to be changed based on position or content.
 
Old 01-20-2010, 07:48 PM   #8
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 244Reputation: 244Reputation: 244
Code:
awk 'BEGIN{
    OFS=FS=":"
    printf "Line to edit: "
    getline linenum <"-"
    printf "Column to edit: "
    getline colnum <"-"
    printf "New value: "
    getline newval <"-"
}
NR==linenum {
    $(colnum) = newval
}1'  file
output

Code:
$ ./shell.sh
Line to edit: 2
Column to edit: 2
New value: Jane Doe
Thomas Peters:Thomas Cruise:Thomas Peters:Betty:Jane
Peter:Jane Doe:John:Peter:Jane
 
Old 04-28-2010, 04:57 PM   #9
iPenguin
LQ Newbie
 
Registered: Sep 2008
Posts: 12

Rep: Reputation: 2
Hello zizou86,

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"

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# get the choice (a line number)
#
read uchoice

# test that the choice is a number only
tst=`echo $uchoice | sed 's/[^0-9]//g'`

# qualified choice
if [[ $tst == $uchoice && ${#uchoice} -gt 0 ]];then

# 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"

# get the new name
read newname

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# qualified new name
if [[ $newname ]];then

# 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

fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# qualified name
if [[ $newname && $confirmed ]];then

# tmp file
dts=`date "+%Y%m%d%H%M%S"`; tmpfile="oldversion-${dts}-${ifile}"

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# backup the original file and
# replace the old name with the new name in the file
#
if [[ $newname ]];then
cat $ifile > $tmpfile
cat $tmpfile | sed 's/:'"$oldname"':/:'"$newname"':/g' > $ifile
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# show and tell
echo -e "\033c"
echo -e "The old name ($oldname) has been changed to ($newname) in file ($ifile).\n"
cat $ifile

else
echo 'Cancelled operation, no changes were made.'
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
Old 04-29-2010, 05:53 AM   #10
zizou86
LQ Newbie
 
Registered: Jan 2010
Posts: 16

Original Poster
Rep: Reputation: 0
Hey great thanks...

Nah long is good. Allows me to learn more =)

Thank you for bothering to dig up an old thread and posting a reply. Really appreciate it.

I shall go and play around with it when I have the time.

Thanks alot.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Sed pattern replacement icyrail Programming 3 10-27-2009 05:33 AM
sed: pattern matching with newlines anjanesh Linux - General 2 02-20-2009 06:36 AM
last pattern with sed? xpto09 Linux - Newbie 6 10-04-2007 08:01 PM
How to get the pattern using sed or awk? ahpin Programming 3 08-02-2007 03:16 AM
Sed pattern matching digitalbrutus Programming 1 08-20-2006 01:37 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:12 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration