Talvez use y//
(comando interno do sed) insteaad de s///
:
$ echo clayii | sed -e '/clayii/ y/clayk/kieio/'
kieiii
Observe que o comando y//
ainda se aplica a toda a linha, não apenas à palavra correspondente.
Acho que encontrei algumas soluções GNU, mas preciso de BSD sed
solutions.
O que eu quero fazer é substituir a palavra inteira de uma só vez. Se a palavra é "clayii", e meu código é sed 's/c/k/g;s/l/i/g;s/a/e/g;s/y/i/g;s/k/o/g'
, eu quero produzir "kieii", mas produz "oieiii" por razões óbvias. Na última seção, ele procura k
e o encontra no começo, mas se ele pesquisou a palavra inteira, nunca faria isso.
Obviamente, "clayii" será diferente o tempo todo, eu quero substituir letras individuais, mas não começar desde o começo, se já tiver substituído o primeiro n
e depois encontrar no começo ele não deve recomeçar. Então, basicamente, ignore o que já foi substituído, se isso for detectável.
Existe uma solução para isso?
Talvez use y//
(comando interno do sed) insteaad de s///
:
$ echo clayii | sed -e '/clayii/ y/clayk/kieio/'
kieiii
Observe que o comando y//
ainda se aplica a toda a linha, não apenas à palavra correspondente.
Com o BSD sed, você pode usar:
sed "s/[[:<:]]clayii[[:>:]]/kieii/g" /path/to/file
você pode passar por cima dele:
echo here is a pat and a tern and a pattern |
sed -e'1{H;x;s/\(.\).*/patternreplace/;x;}' \
-eG -e'/\(.*\)\(.*\n\)\(\n\)\n/!{P;d;}' \
-e's///;t-' \
-e:- -e's/\(\n\)\(.\)\(.*\n\)\(.\)//;t-' \
-e's/\n//;P;d'
here is a pat and a tern and a replace
Isso faz o caractere de substituição por caractere progredindo da esquerda para a direita. Ele desloca o primeiro delimitador para a direita do caractere substituído para cada substituição. Você pode ver o que quero dizer se colocar um comando l
ook logo antes da substituição do loop t
ested após -e:-
:
here is a pat and a tern and a \npattern\nreplace$
here is a pat and a tern and a r\nattern\neplace$
here is a pat and a tern and a re\nttern\nplace$
here is a pat and a tern and a rep\ntern\nlace$
here is a pat and a tern and a repl\nern\nace$
here is a pat and a tern and a repla\nrn\nce$
here is a pat and a tern and a replac\nn\ne$
here is a pat and a tern and a replace\n\n$
here is a pat and a tern and a replace
Se você realmente está procurando por uma espécie de tradução, pode fazer isso também. Eu escrevi isso antes como uma resposta para outra pergunta:
It looks doable - you just have to sort of shift-in/shift-out:
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
...it isn't easy, though.
Essa volta um pouco também, mas não tanto.
As is true of most complicated problems, though, it is way easier if you use two
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
Com um BSD sed
, você desejará usar uma nova linha literal no lugar do n
nos \n
escapes na substituição à direita do primeiro sed
lá.