Como as opções '-s', '-t' e '-c' do comando tr funcionam no Unix?

12

Estou confuso sobre a forma -s, -te -copções de trabalho no tr comando. Quando eu faço

echo I am a good boy | tr good bad

Eu recebo a saída:

I am a bddd bdy

Isso é bastante compreensível, pois oé repetido em good. A última mudança possível no lugar de oé de, portanto, a saída.

Agora quando eu faço

echo I am a good boy | tr -s good bad

a saída é

I am a bd bdy

A -sopção deve espremer todas as ocorrências repetidas de cada caractere no conjunto 1 em uma única ocorrência e depois alterar cada caractere no conjunto 1 para o caractere correspondente no conjunto 2, que está na mesma posição.

Então deveria ter sido

I am a bad bay.

Por que a mudança?

Além disso, quando eu faço

echo I am a good boy | tr -c good bad

eu recebo dddddddgoodddodd

Como funciona a -copção tr, referindo-se a este exemplo?

E finalmente: como mudar de um garoto bom para um garoto ruim .... :): P Ou seja,

echo I am a good boy | tr <something>dá-me a saída como: I am a bad boy.

dig_123
fonte

Respostas:

12

-s Alternar: Apertar (remover caracteres repetidos)

echo i am a good boy | tr -s good bad

resultado: i am a bd bdy

Há duas coisas acontecendo nos bastidores que fazem isso acontecer. Primeiramente, se o segundo argumento to trfor menor que o primeiro, o último caractere no 2º arg será repetido para torná-lo com o mesmo tamanho do primeiro. Portanto, o comando equivalente é:

echo i am a good boy | tr -s good badd

A outra coisa que está acontecendo é que, quando os caracteres do primeiro argumento são repetidos, eles substituem qualquer ocorrência anterior (estou me referindo aos dois oosegundos good). Isso torna o comando agora equivalente a:

echo i am a good boy | tr -s god bdd

(o segundo opara dsubstituição substitui o anterior opara asubstituição, tornando-o redundante)

Sem o -sinterruptor, a saída seria

i am a bddd bdy

Com a -sopção tr'squeezes', qualquer caractere repetido listado no último argumento sai da saída final:

i am a bd bdy

-c Switch: Complemento

A -copção é usada para corresponder ao complemento do primeiro argumento (ou seja, todos os caracteres não listados na arg 1). Como resultado, o arg 1 conterá muitas letras (256-3). Agora, o mesmo acontece com o arg 2, como no caso anterior: o caractere final do Arg 2 é repetido para corresponder ao comprimento ou ao Arg 1. Portanto, a declaração original:

echo i am a good boy | tr -c good bad

é equivalente a:

echo i am a good boy | tr abcefhijklmnp... baddddddddddd...

(observe a falta e g, no primeiro conjunto, observe também que substituirá todos os outros caracteres no segundo conjunto - incluindo o caractere de espaço)odd

É por isso que i am a good boyse transformadddddddgoodddodd

Mais informações aqui: http://www.linuxjournal.com/article/2563

ltn100
fonte
Geralmente correto, exceto que a -sopção faz trcom que todos os caracteres do último argumento sejam espremidos tr(não o primeiro, como você diz) que são repetidos na entrada. Isso é observado no artigo que você vinculou e é explicado no último parágrafo na seção "Descrição" da página de manual .
ravron 28/02/19
4

Seu entendimento de -sestá incorreto, ele substitui ocorrências repetidas de caracteres no conjunto 1 na entrada por um único caractere. não modifica o conjunto, por exemplo.

echo i am a good boy | tr -s god bad

i am a bad bay

A -copção substitui o conjunto 1 pelo seu complemento (ou seja, o conjunto de todos os caracteres não contidos no conjunto 1). Você pode usar isso para remover todos, exceto os caracteres especificados, por exemplo.

echo i am a good boy | tr -cd gobdy

saídas

goodboy
Hasturkun
fonte
: Eu entendi seu ponto em relação à opção -s, mas minha pergunta é: como: echo eu sou um bom garoto | tr -s good bad está dando saída como: eu sou um bd bdy isso só é possível quando isso acontece: primeiro eu sou um bom garoto é alterado para eu sou um bddd bdy, então a opção -s altera as ocorrências de vários d's para single ou seja: eu sou um bddd bdy, em seguida, muda para eu sou um bdd bdy é isso que realmente está acontecendo? por favor, divida isso para mim, mesmo com a opção -c como echo eu sou um bom garoto | tr -cd gobdy dando isso: goodboy
1

As outras respostas coberto tr's -s, -te -copções, mas para ser completo:

Você está tendo problemas porque pegou a ferramenta errada.

  • tr é para transformações de caracteres
  • sed é para edição de stream.

Como os dois goode a badsequência de caracteres no fluxo sedsão uma correspondência melhor.

echo I am a good boy | <something> dá-me a saída como: I am a bad boy

$ echo I am a good boy | sed s/good/bad/g
I am a bad boy

O s/..../..../é substituto. O que corresponder à primeira expressão regular será substituído pela segunda. A /gbandeira no final é para substituição global, dessa forma, todas as ocorrências serão substituídas e não apenas a primeira.

$ echo I am a good boy and a good boy is me. | sed s/good/bad/
I am a bad boy and a good boy is me.

$ echo I am a good boy and a good boy is me. | sed s/good/bad/g
I am a bad boy and a bad boy is me.
Aaron Goldman
fonte
0

sim. exatamente!

tr -s substitui instâncias de caracteres repetidos por um único caractere.

(via página de manual.)

então, é assim:

converte goodpara bddd. instâncias repetidas são 3 'd's.

portanto, substitui essas três instâncias por uma única instância.

é isso que torna bd. :)

Rahul Mishra
fonte
2
Não esperamos que todas as respostas sejam perfeitas, mas as respostas com ortografia, pontuação e gramática corretas são mais fáceis de ler.
Ashildr