Alex van Es
Alex van Es

Reputation: 1181

Replace chars after column X

Lets say my data looks like this

iqwertyuiop

and I want to replace all the letters i after column 3 with a Z.. so my output would look like this

iqwertyuZop

How can I do this with sed or awk?

Upvotes: 1

Views: 73

Answers (5)

glenn jackman
glenn jackman

Reputation: 247012

Perl is handy for this: you can assign to a substring

$ echo "iiiiii" | perl -pe 'substr($_,3) =~ s/i/Z/g'
iiiZZZ

Upvotes: 3

hek2mgl
hek2mgl

Reputation: 158110

The most intuitive way would be to use awk:

awk 'BEGIN{FS="";OFS=FS}{for(i=4;i<=NF;i++){if($i=="i"){$i="Z"}}}1' file

FS="" splits the input string by characters into fields. We iterate trough character/field 4 to end and replace i by Z.

The final 1 evaluates to true and make awk print the modified input line.


With sed it looks not very intutive but still it is possible:

sed -r '
    h                      # Backup the current line in hold buffer
    s/.{3}//               # Remove the first three characters
    s/i/Z/g                # Replace all i by Z
    G                      # Append the contents of the hold buffer to the pattern buffer (this adds a newline between them)
    s/(.*)\n(.{3}).*/\2\1/ # Remove that newline ^^^ and assemble the result
' file         

Upvotes: 1

peak
peak

Reputation: 116880

(1) Here's a short-and-simple way to accomplish the task using GNU sed:

sed -r -e ':a;s/^(...)([^i]*)i/\1\2Z/g;ta'

This entails looping (t), and so would not be as efficient as non-looping approaches. The above can also be written using escaped parentheses instead of unescaped characters, and so there is no real need for the -r option. Other implementations of sed should (in principle) be up to the task as well, but your MMV.

(2) It's easy enough to use "old awk" as well:

awk '{s=substr($0,4);gsub(/i/,"Z",s); print substr($0,1,3) s}'

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 204099

It's not clear what you mean by "column" but maybe this is what you want using GNU awk for gensub():

$ echo iqwertyuiop | awk '{print substr($0,1,3) gensub(/i/,"Z","g",substr($0,4))}'
iqwertyuZop

Upvotes: 3

Brian
Brian

Reputation: 2242

This would totally be ideal for the tr command, if only you didn't have the requirement that the first 3 characters remain untouched.

However, if you are okay using some bash tricks plus cut and paste, you can split the file into two parts and paste them back together afterwords:

paste -d'\0' <(cut -c-3 foo) <(cut -c4- foo | tr i Z)

The above uses paste to rejoin together the two parts of the file that get split with cut. The second section is piped through tr to translate i's to Z's.

Upvotes: 1

Related Questions