tags:

views:

576

answers:

3

Hello everyone. I got a document that fields are separated by a colon(:) where I need to change the second field from time to time. The document looks like this:

name1:UhX.PPFW7$YhPMH0BISY:23490::::::
name2:1./0oV$GEs6WJpE$LHXhy:19239:0:29388:2::29302:
...

The second field of the file will change occasionally and may contain a couple regular expression characters ($ .) and a forward slash.

I'd like to replace only the second field as the data that follows it may be different in the future. If I do:

sed -e "s~^name2:.*:~name2:aTest\$repl.ace:~g" tst

The text to the right of the second column is lost:

name2:aTest$repl.ace:

(i.e. the '19239:0:29388:2::29302:'). Is there a way that sed can replace a varying column and preserve the rest of the line? Or, possibly, is there a better program to do this?

A: 

Sed probably isn't the best tool for this because if doesn't really know about fields. Consider awk (which has a built in concept of fields) instead:

$ awk -F : 'NF>=2{split($0,a,":");a[2]="new sting";printf(a[1]);for(i=2;i<=NF;i++){printf":%s",a[i]};printf("\n");}' <input file>

or formatted for readability:

awk -F : 'NF>=2 {
                   split($0,a,":");
                   a[2]="new sting";
                   printf(a[1]);
                   for(i=2;i<=NF;i++){
                     printf":%s",a[i]
                   };
                   printf("\n");
                 }' <input file>

For generality you might want to replace the ":" with FS. Also worth looking at is this join function which would make the implementation cleaner if you a writing a script rather than running on the command line.

This implementation assumes that you want to replace all the second fields. If yu need to select only some of the lines for replacement, change the pattern to

$2=="string to match"

or

$2~/regex to match/
dmckee
heh, awk is a bit over my head at the time but it does work. Thank you.
Todd Partridge
A: 

Try this:

perl -pe 's~^name2:.*?:~name2:aTest\$repl.ace:~g' test
ennuikiller
Beginning to like perl - all the syntaxes it uses (that I've seen) are easy to remember syntax. Thanks for the tip ennuikiller.
Todd Partridge
A: 

The simplest way is to change the .* in your regexp to match only what can actually appear in the second field, eg:

sed -e "s~^name2:[^:]*:~name2:aTest\$repl.ace:~g" tst

([^:]* == anything that doesn't contain a colon), or:

sed -e "s~^name2:[$./0-9a-zA-Z]*:~name2:aTest\$repl.ace:~g" tst

([blah]* == any number of the characters listed)

Anthony Towns
Hey that's great. Was wondering if this was possible in sed. Thought I might be looking at a more-complicated command. Appreciate the tip, Anthony.
Todd Partridge