Os comandos sed 'y' podem ser aplicados apenas ao texto correspondente (em vez de à linha inteira)

2

Depois de escrever esta resposta , eu fiz alguns googling para descobrir se eu poderia fazer o comando sed y// ser aplicado apenas na correspondência e não na linha inteira. Não consegui encontrar nada relevante.

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

Em outras palavras, se a palavra de pesquisa (clayii) for apenas uma das muitas palavras na linha de entrada, eu quero que o comando y// seja aplicado somente para essa palavra e não para o restante da linha.

i.e. Eu não quero isso:

$ 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

Isso é possível em sed ? ou preciso usar algo mais capaz como perl ?

    
por cas 02.12.2015 / 01:34

3 respostas

5

Não, o comando y se aplica a todos os caracteres correspondentes no espaço padrão. De acordo com a sed documentação POSIX (enfatize a minha):

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

página OSX / BSD man :

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

e GNU sed info página:

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.

Claro, você pode usar o buffer de retenção para salvar o espaço de padrão atual e, depois, reter apenas a correspondência, transliterar e restaurar o espaço de padrão substituindo a correspondência inicial com o resultado. comparar

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

com

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

mas assim que você começa a adicionar padrões / requisitos, fica complicado.

    
por 02.12.2015 / 03:00
2

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

    
por 02.12.2015 / 03:26
1

Parece factível - você só precisa mudar de posição:

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

... não é fácil, no entanto.

Como é o caso dos problemas mais complicados, porém, é caminho mais fácil se você usar dois sed s:

echo can ccccc ccccccccclayii sed clay ignore \
     every cclayii thing but the matching word\
     - cclayiicclayii |
sed -e's/\(cclayii\)*/\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
    
por 02.12.2015 / 12:00