SED Command – Apply ‘y’ Commands Only to Matching Text

sedtext processing

After writing this answer, I did some googling to find out if I could make the sed y// command be applied only to the match and not to the entire line. I wasn't able to find anything relevant.

$ echo clayii | sed -e '/clayii/ y/clayk/kieio/'
kieiii

In other words, if the search word (clayii) is just one of many words in the input line, I want the y// command to be applied only to that word and not to the remainder of the line.

i.e. I don't want this:

$ echo can sed ignore everything but the matching word - clayii | 
    sed -e '/clayii/ y/clayk/kieio/'
ken sed ignore everithing but the metkhing word - kieiii

Is that possible in sed? or do i need to use something more capable like perl?

Best Answer

No, the y command applies to all matching characters in the pattern space. Per the POSIX sed documentation (emphasize mine):

[2addr]y/string1/string2/
             Replace all occurrences of characters in string1
             with the corresponding characters in string2.

OSX/BSD man page:

[2addr]y/string1/string2/
             Replace all occurrences of characters in string1 in the pattern
             space with the corresponding characters from string2.

and GNU sed info page:

y/source-chars/dest-chars/
             Transliterate any characters in the pattern space which match any of
             the source-chars with the corresponding character in dest-chars.

Sure, you could use the hold buffer to save current pattern space then retain only the match, transliterate and restore the pattern space replacing the initial match with the result e.g. compare

sed 'y/words/evles/' <<<'words whispered by the drows'

with

sed 'h;s/.*\(drows\).*/\1/;y/words/evles/;G;s/\(.*\)\n\(.*\)drows\(.*\)/\2\1\3/' <<<'words whispered by the drows'

but as soon as you start adding patterns/requirements it gets complicated.

Related Question