Los commands `y` de sed pueden aplicarse solo al text coincidente (en lugar de a toda la línea)

Después de escribir esta respuesta , busqué en Google para averiguar si podía hacer que el command sed y// se aplicara solo a la coincidencia y no a toda la línea. No pude encontrar nada relevante.

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

En otras palabras, si la palabra de búsqueda (clayii) es solo una de muchas palabras en la línea de input, quiero que el command y// se aplique solo a esa palabra y no al rest de la línea.

es decir, no quiero esto:

 $ 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 

¿Es eso posible en sed ? ¿o necesito usar algo más capaz como perl ?

No, el command y aplica a todos los caracteres coincidentes en el espacio del patrón. Según la documentation POSIX sed (enfatizar el mío):

  [ 2addr ] y / string1 / string2 /
              Reemplazar todas las apariciones de caracteres en cadena1
              con los caracteres correspondientes en string2 . 

Página de man OSX / BSD :

 [2addr] y / string1 / string2 /
              Reemplazar todas las ocurrencias de caracteres en string1 en el patrón
              espacio con los caracteres correspondientes de string2 . 

y la página de GNU sed info :

  y / source-chars / dest-chars /
              Transliterar cualquier carácter en el espacio del patrón que coincida con cualquiera de
              los caracteres fuente con el carácter correspondiente en dest-chars . 

Claro, podría usar el búfer de retención para save el espacio del patrón actual, luego retener solo el partido, transcribir y restaurar el espacio del patrón reemplazando la coincidencia inicial con el resultado, por ejemplo comparar

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

con

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

pero tan pronto como empiezas a agregar patrones / requisitos se vuelve complicado.

El perl: perl -pe 's{(clayii)}{ ($new=$1) =~ tr/clayk/kieio/; $new }e' file perl -pe 's{(clayii)}{ ($new=$1) =~ tr/clayk/kieio/; $new }e' file

Parece factible, solo tienes que cambiar de input / salida:

 echo can ccccc ccccccccclayii sed clay ignore \ every cclayii thing but the matching word\ - cclayiicclayii | sed -e'y/ /\n/' \ -eh -e's/\(cclayii\)\1*/ & /g;x;s// /g;s/^/ /' \ -ex -e's//./;s/\([^ ]* *\)\{2\}/\1 /g;s/^/ /' \ -e'y/clayk/kieio/;G;t$' -e:$ \ -e'/^ \n /{s///;y/ \n/\n /;}' \ -et -e's/^ *\([^ ]*\) \(.* \n [^ ]*\) /\2\1/;t$' 

 can ccccc ccccccckkieiii sed clay ignore every kkieiii thing but the matching word - kkieiiikkieiii 

… no es fácil, sin embargo.


Como es el caso de los problemas más complicados, es mucho más fácil si usas dos sed :

 echo can ccccc ccccccccclayii sed clay ignore \ every cclayii thing but the matching word\ - cclayiicclayii | sed -e's/\(cclayii\)\1*/\n&\n /g;G;s/^/ /'| sed -e'/^ /!y/clayk/kieio/;/./{H;d;}' \ -e'x;s/\n \{0,1\}//g' 

 can ccccc ccccccckkieiii sed clay ignore every kkieiii thing but the matching word - kkieiiikkieiii