Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a file containing lines:

india;austria;japan;chile
china;US;nigeria;mexico;russia

I want to replace all the occurences of semicolon on each line with e.g. ;NEW;, but starting from the 2nd occurence only. The result should look like this:

india;austria;NEW;japan;NEW;chile
china;US;NEW;nigeria;NEW;mexico;NEW;russia

I tried this with gsub, but it replaces all the occurences: awk '/;/{gsub(/;/,";NEW;") }{print}'

share|improve this question
add comment

4 Answers

up vote 5 down vote accepted

The awk solution is much longer, but is easier to make it generic:

awk -F\; '{for(i=1;i<NF;i++)printf"%s;%s",$i,(i>=2)?"NEW;":"";print$NF}' replacefile

Is possible to do it with sed too, making a loop with the t command and always replacing the 2nd (or whichever you want) separator into some temporary mark (usually \n):

sed ':b;s/;/\n/2;tb;s/\n/;NEW;/g' replacefile
share|improve this answer
add comment

There's a flag for GNU sed's s/// command that does this:

sed 's/;/;NEW;/2g' <<END
india;austria;japan;chile
china;US;nigeria;mexico;russia
END

outputs

india;austria;NEW;japan;NEW;chile
china;US;NEW;nigeria;NEW;mexico;NEW;russia

See https://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command

The s command can be followed by zero or more of the following flags:

g

Apply the replacement to all matches to the regexp, not just the first.

number

Only replace the numberth match of the regexp. Note: the posix standard does not specify what should happen when you mix the g and number modifiers, and currently there is no widely agreed upon meaning across sed implementations. For GNU sed, the interaction is defined to be: ignore matches before the numberth, and then match and replace all matches from the numberth on.

...

(emphasis mine)

share|improve this answer
2  
Great! I never noticed you can combine g and number flags. –  manatwork Mar 18 '13 at 13:06
add comment

I'd do this in two steps:

First, replace all semicolons with ;NEW;:

sed -e s/\;/\;NEW\;/g

Then replace the first ;NEW; with a semicolon:

sed -e s/\;NEW\;/\;/

You can use a pipe to do both replaces on one line. Here's an example:

$ more replacefile 
india;austria;japan;chile;
china;US;nigeria;mexico;russia
$ cat replacefile |sed -e s/\;/\;NEW\;/g  |sed -e s/\;NEW\;/\;/
india;austria;NEW;japan;NEW;chile;NEW;
china;US;NEW;nigeria;NEW;mexico;NEW;russia
share|improve this answer
    
thanks, but i was hoping that i could get something generalized for an nth match(1,2,3,4 or 5) –  munish Mar 18 '13 at 10:55
add comment

I can do it with more code but no loops!

Data

china;US;nigeria;mexico;russia
iindia;austria;japan;chile

Script

BEGIN{ FS=";" }{
    insert=$param
    ix=index($0, insert) + length(insert)

    if (NF <= $param) {
            rest = substr($0,ix,length($0))
            gsub(";",";NEW;",rest)
            line = substr($0,0,ix) rest

            gsub(";;",";",line)
            gsub(";$","",line)
            print line

} else {print}}

Example

 Microknoppix v # awk -f replaceNth.awk -v param=2 countries
 china;US;NEW;nigeria;NEW;mexico;NEW;russia
 iindia;austria;NEW;japan;NEW;chile
share|improve this answer
    
Oops, sorry for the failed correction. But something is still not completely correct. There should be “NEW” marks after all fields starting with the param th one. –  manatwork Mar 18 '13 at 12:17
    
Oh, I misunderstood the problem :\ –  Ярослав Рахматуллин Mar 18 '13 at 12:20
    
I think this deserves an upvote because it's obviously easier to memorize, maintain and explain. In fact, this is the new "Hello world" –  Ярослав Рахматуллин Mar 18 '13 at 12:49
    
Much better, but will still fail string like “china;dominican republic;nigeria; dominica;russia” and param=4. (The space in the string is just to satisfy the Markdown parser's caprice.) –  manatwork Mar 18 '13 at 13:03
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.