LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
Search this Thread
Old 06-17-2005, 08:27 AM   #1
sgracelin
LQ Newbie
 
Registered: Jun 2005
Posts: 10

Rep: Reputation: 0
Replacing a particular position in a file


Hi,

I have a file content as follows. The file content has got 5 columns each separated by ':' as field separator. I want to replace the value in the second column. ie if a value in second column is 333331 I have to replace with 777771. But if 333331 is in first or someother column other than 2nd column then it should not be replaced. Anyway to do this in Sed or AWK??

The file content as follows:
"33333110000":"333331238283":NULL:0:3
"33333110000":"444441001362":NULL:1:2
"9880222221":"333331708559":NULL:0:3
"9880222221":"333331001362":NULL:1:2
"9880222221":"444441001362":NULL:2:2
"9880222222":"333331414216":NULL:0:3
"9880222223":"333331858924":NULL:0:3
"9880222223":"333331001362":NULL:1:2
"9880222224":"333331803679":NULL:0:3
"9880222224":"333331001362":NULL:2:2
"9880333331":"333331733603":NULL:0:3
"9880333331":"444441001362":NULL:3:2


333331 in the second column should be replaced but 333331 in first column should not be replaced.

Thanks!!
 
Old 06-17-2005, 08:56 AM   #2
zulfilee
Member
 
Registered: Apr 2004
Location: India
Distribution: Redhat,Fedora
Posts: 430

Rep: Reputation: 39
Ok one way of doing it will be
I`ve replaceed 333331 with OOO


cat filename | sed "s/^\([^:]*:[^:]*\)333331\([^:]*:\)/\1OOO\2/"

But the above regex is too long
I`m trying for a better one

Cheers
Z
 
Old 06-17-2005, 12:35 PM   #3
hpladd
Member
 
Registered: Feb 2003
Distribution: Kubuntu
Posts: 142

Rep: Reputation: 15
Hey Z,

I'm studying linux and am having trouble understanding the sed command you detailed. It works. I tried it, but I don't understand it.

Here's my comprehension of the command (skipping over the cat portion):

1. s initiates a substitute operation.
2. ^ starts the search a beginning of the lines/strings
3. /(/) sequence places column A : column B into a buffer.
4. The first argument of the substitute operation is provided "33331"
5. Then /(/) places the first column of characters into a buffer. (again?)
6. The second argument of the substitute command is provided "\1000\2\/" This portion seems to say, recall buffer #1 and replace 33331 of the buffered data with 000, and then it recalls buffer 2.

I know I've taken a wrong turn in my thinking here. Would you be kind enough to point me to where I skipped track?

Also I would think that the command would need to end with /g.

Thanks
 
Old 06-17-2005, 04:23 PM   #4
jonaskoelker
Senior Member
 
Registered: Jul 2004
Location: Denmark
Distribution: Ubuntu, Debian
Posts: 1,524

Rep: Reputation: 46
Token by token:
sed -- you got that right
s/ -- substitute the following with FOO
^ -- beginning of line
\( -- begin group (which you call buffer)
[^:]* -- match any number of any char that's not a colon; `*' means any number of (what preceeds it); [^abcd] means "anything except abcd" (in this case it's just `:').
: -- then match a colon
[^:]* -- then match any no. of not-colon again
\) -- end group 1
333331 -- the text you want to be replaced with (some other text).
\([^:]*:\) -- should be more or less obvious
/ -- # FOO begins here
\1 -- the contents of group 1 (i.e. everything up until 333331)
OOO -- the replacement text.
\2 -- the rest of the line.
/ -- # FOO ends here

Quote:
Also I would think that the command would need to end with `g'.
No--`g' means `global'. That is, replace *all* occurences of the pattern, not just the first. But since you only want to replace one pattern (the first), you don't need the g here.

I think this is more elegant, more correct and possibly faster too:
Code:
$ sed -r 's/^([^:]*:)333331/\1777771/' filename
It might be that `\1777771' gets interpreted as group number 1777771; try `\1(777771)' instead.

If all else fails, RTM

hth --Jonas
 
Old 06-20-2005, 12:45 AM   #5
sgracelin
LQ Newbie
 
Registered: Jun 2005
Posts: 10

Original Poster
Rep: Reputation: 0
zulfilee's answer worked ..

Last edited by sgracelin; 06-21-2005 at 01:57 AM.
 
Old 06-20-2005, 03:41 AM   #6
zulfilee
Member
 
Registered: Apr 2004
Location: India
Distribution: Redhat,Fedora
Posts: 430

Rep: Reputation: 39
Ok here is a better one


awk 'BEGIN{FS=":";OFS=":"}
{gsub("333331","AAAA",$2); print $0}' filename

BEGIN -> Start of script
FS,OFS are input and output field seperators.
[By default awl takes space as field separator]

gsub is a function which has this format
gsub(Pattern,Replacement,StringPosition)
And print $0 will printout the output


awk -F ":" '{gsub("333331","AAAA",$2); print $0}' filename
will also work .
Here we specify the filed seperator outside

[But ideally sub should be used instead of gsub.
gsub is global substitution]

Cheers
Z
 
Old 06-20-2005, 05:50 AM   #7
sgracelin
LQ Newbie
 
Registered: Jun 2005
Posts: 10

Original Poster
Rep: Reputation: 0
Hi Z and everyone,

My file content is

"4444412000 ":"444441001362":"Kodiak2Grp "
"9880222221 ":"333331001362":"TestGrp1 "
"3333312221 ":"333331333331":"TestGrp1 "

The file has three fields....I have to replace 333331 in the second column only...the script

If the first 6 characters match the string then only it should be replaced..[if the last 6 or the any combination of six characters in the second column matches other than first 6 characters, then it should not be replaced]..

Last edited by sgracelin; 06-21-2005 at 01:58 AM.
 
Old 06-20-2005, 06:46 AM   #8
zulfilee
Member
 
Registered: Apr 2004
Location: India
Distribution: Redhat,Fedora
Posts: 430

Rep: Reputation: 39
sed 's/^\([^:]*:"\)333331\([^:]*:\)/\1AAAA\2/' filename

Ive just removed the [^:]* and put a explicit " to the previous sed command.Means look for the first 6 chars

In awk it`ll be a bit long


awk -F ":" '{if ($2 ~ /^"333331/)
{sub("333331","AAA",$2) ;print $0}
else {print $0}} ' filename

Here we check if second string [: separated ] is staring with 33331
Or we print the line as it is.


You can write it more shortly too
Cheers
Z
 
Old 06-20-2005, 07:19 AM   #9
sgracelin
LQ Newbie
 
Registered: Jun 2005
Posts: 10

Original Poster
Rep: Reputation: 0
thanks..

Last edited by sgracelin; 06-21-2005 at 01:56 AM.
 
Old 06-20-2005, 08:13 AM   #10
zulfilee
Member
 
Registered: Apr 2004
Location: India
Distribution: Redhat,Fedora
Posts: 430

Rep: Reputation: 39
sed "s/^\([^:]*:\"\)$oldtr\([^:]*:\)/\1$newstr\2/"

SIngle quotes will mask the variable and try to serach is as $oldstr and not 333331

Just go for double quotes but then you have to escape the doulbe quote inside search with a backslash i.e \"

Cheers
Z
 
Old 06-23-2005, 04:47 AM   #11
sgracelin
LQ Newbie
 
Registered: Jun 2005
Posts: 10

Original Poster
Rep: Reputation: 0
How to replace the string '33331' which comes in the beginning of 7th column alone has to be replaced...other 333331 in other columns should be retained as such..


2:"333331333331333331":"333331333331333331":"333331":1:1:1:"333331333331":"333331333331333331":1:1
12:"333331333331333331":"222221222221222221":"222221":1:1:1:"222221222221":"222221222221222221":1:1
12:"222221222221222221":"333331333331333331":"222221":1:1:1:"222221222221":"222221222221222221":1:1
12:"222221222221222221":"222221222221222221":"222221":1:1:1:"333331333331":"222221222221222221":1:1
12:"222221222221222221":"222221222221222221":"222221":1:1:1:"222221222221":"333331333331333331":1:1
12:"222221222221222221":"222221222221222221":"222221":1:1:1:"222221222221":"222221222221222221":1:1
12:"333331222221222221":"333331333331222221":"222221":1:1:1:"333331333331":"222221222221222221":1:1
12:"333331222221222221":"333331333331222221":"222221":1:1:1:"222221222221":"333331333331222221":1:1
 
Old 06-23-2005, 05:45 AM   #12
zulfilee
Member
 
Registered: Apr 2004
Location: India
Distribution: Redhat,Fedora
Posts: 430

Rep: Reputation: 39
The same awk script can be used as such

awk -F ":" '{if ($8 ~ /^"333331/)
{sub("333331","AAA",$8) ;print $0}
else {print $0}} ' filename

The pattern was in the 8 th column

In sed
sed 's/^\(\([^:]*:\)\{7\}\)"333331\(..*\)/\1"AAAA\3/' filename

^\(\([^:]*:\)\{7\}\) -> Here we Look for a pattern that comes as something:something 7 times.
"333331 -> Then we search for the string in the 8th field
\(..*\) -> The rest of the line

\1 -> is the first \( \) enclosure
and \3 is the last.


But in sed it doesnt look that good.

Cheers
Z
 
Old 06-23-2005, 05:56 AM   #13
sgracelin
LQ Newbie
 
Registered: Jun 2005
Posts: 10

Original Poster
Rep: Reputation: 0
If I used AWK then the field separator disappears for those rows where the values were replaced...why is it so??

Output comes like this...

12 "333331333331333331" "333331333331333331" "333331" 1 1 1 "AAA333331" "333331333331333331" 1 1
12:"333331333331333331":"222221222221222221":"222221":1:1:1:"222221222221":"222221222221222221":1:1
12:"222221222221222221":"333331333331333331":"222221":1:1:1:"222221222221":"222221222221222221":1:1
12 "222221222221222221" "222221222221222221" "222221" 1 1 1 "AAA333331" "222221222221222221" 1 1
12:"222221222221222221":"222221222221222221":"222221":1:1:1:"222221222221":"333331333331333331":1:1
12:"222221222221222221":"222221222221222221":"222221":1:1:1:"222221222221":"222221222221222221":1:1
12 "333331222221222221" "333331333331222221" "222221" 1 1 1 "AAA333331" "222221222221222221" 1 1
12:"333331222221222221":"333331333331222221":"222221":1:1:1:"233333122221":"333331333331222221":1:1

Command:

awk -F ":" '{if ($8 ~ /^"333331/)
> {sub("333331","AAA",$8) ;print $0}
> else {print $0}} '

Any ideas??
 
Old 06-23-2005, 06:26 AM   #14
zulfilee
Member
 
Registered: Apr 2004
Location: India
Distribution: Redhat,Fedora
Posts: 430

Rep: Reputation: 39
Oops sorry then try this

awk 'BEGIN {FS=":";OFS=":"}
{if ($8 ~ /^"333331/)
> {sub("333331","AAA",$8) ;print $0}
> else {print $0}' filename

What happenned was awk has default OFS[o/p file seperator ] as space
this has replaced your orginal fs ":"

Cheers
Z
 
Old 06-23-2005, 06:40 AM   #15
sgracelin
LQ Newbie
 
Registered: Jun 2005
Posts: 10

Original Poster
Rep: Reputation: 0
Thanks for the info(OFS)...Gr88
 
  


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
Replacing a particular position in a file thru shell script in Linux sgracelin Programming 7 06-22-2005 07:04 AM
Replacing a particular position in a file sgracelin Linux - Newbie 1 06-20-2005 05:54 PM
replacing characters in a file with others pcdude Linux - General 6 01-19-2005 12:29 AM
Vi - retain position in file between invokations of vi Xanadu Linux - Software 1 12-23-2004 02:33 PM
read file and analyze position j-me Linux - Newbie 3 07-18-2003 05:54 PM


All times are GMT -5. The time now is 11:00 AM.

Main Menu
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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration