Os comandos tr podem ser encadeados para evitar múltiplos processos tr em um pipeline?

7

Eu tenho um monte de arquivos txt, eu gostaria de mostrá-los com letras maiúsculas, apenas alfabéticos e uma palavra por linha, eu posso fazer isso com vários comandos tr em um pipeline como este:

tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n'

É possível fazer isso em uma varredura? Eu poderia escrever um programa em C para fazer isso, mas eu sinto que há uma maneira de fazer isso usando tr , sed , awk ou perl .

    
por tlehman 11.02.2015 / 00:40

3 respostas

6

Você pode combinar várias traduções (exceto casos complexos envolvendo conjuntos dependentes de localidade sobrepostos), mas você não pode combinar a exclusão com a tradução.

<doyle_sherlock_holmes.txt tr -d '[:punct:]' | tr '[:upper:] ' '[:lower:]\n'

Duas chamadas para tr provavelmente serão mais rápidas do que uma única chamada para ferramentas mais complexas, mas isso depende muito do tamanho de entrada, das proporções de caracteres diferentes, da implementação de tr e das ferramentas concorrentes , no sistema operacional, no número de núcleos, etc.

    
por 11.02.2015 / 00:54
4

Aqui estão algumas abordagens:

  • GNU grep e tr : encontre todas as palavras e coloque-as em minúsculas

    grep -Po '\w+' file | tr '[A-Z]' '[a-z]'
    
  • GNU grep e perl: como acima, mas o perl manipula a conversão para minúsculas

    grep -Po '\w+' file | perl -lne 'print lc()'
    
  • perl: encontre todos os caracteres alfabéticos e imprima-os em letras minúsculas (obrigado @steeldriver):

    perl -lne 'print lc for /[a-z]+/ig' file
    
  • sed: remova todos os caracteres que não sejam alfabéticos ou espaços, substitua todos os caracteres alfabéticos por suas versões em minúsculas e substitua todos os espaços por novas linhas. Observe que isso pressupõe que todo espaço em branco seja espaços, sem guias.

    sed 's/[^a-zA-Z ]\+//g;s/[a-zA-Z]\+/\L&/g; s/ \+/\n/g' file
    
por 11.02.2015 / 00:59
3

Sim. Você pode fazer isso com tr em uma localidade ASCII (que é, de qualquer forma, para um GNU tr , o que é seu único atributo) . Você pode usar as classes POSIX ou pode referenciar os valores de byte de cada caractere por número octal. Você também pode dividir as transformações entre os intervalos.

LC_ALL=C tr '[:upper:]
LC... tr ... | tr -s \n
-13-1403-7' '[:lower:][\n*]' <input

O comando acima transformaria todos os caracteres maiúsculos para minúsculos, ignoraria totalmente os caracteres minúsculos e transformaria todos os outros caracteres em novas linhas. Claro, então você acaba com uma tonelada de linhas em branco. A troca de repetições tr -s queeze poderia ser útil nesse caso, mas se você usá-la junto com a transformação [:upper:] to [:lower:] , você acabará apertando os caracteres maiúsculos também. Dessa forma, ainda requer um segundo filtro como ...

LC... tr ... | grep .

... ou ...

LC_ALL=C tr -sc '[:alpha:]' \n <input | tr '[:upper:]' '[:lower:]'

... e assim acaba sendo muito menos conveniente do que fazer ...

tr '
tr '
LC_ALL=C tr '[:upper:]
LC... tr ... | tr -s \n
-13-1403-7' '[:lower:][\n*]' <input
-7' '[A*64][B*64][C*64][D*64]' </dev/urandom | dd bs=32 cbs=8 conv=unblock,lcase count=1 dadbbdbd ddaaddab ddbadbaa bdbdcadd
-7' '[1*25][2*25][3*25][4*25][5*25][6*25][7*25][8*25][9*25][0*]' </dev/random

... que comprime a -c omplement de caracteres alfabéticos por sequência em uma única linha nova em uma peça, e então faz a transformação superior para inferior no outro lado da linha.

Isso não quer dizer que intervalos dessa natureza não sejam úteis. Coisas como:

LC... tr ... | grep .

... pode ser muito útil, pois converte os bytes de entrada para todos os dígitos em um espectro de seus valores. Não desperdice, não quero, você sabe.

Outra maneira de fazer a transformação pode envolver dd .

LC_ALL=C tr -sc '[:alpha:]' \n <input | tr '[:upper:]' '[:lower:]'

Como o dd pode fazer as duas conversões unblock e lcase ao mesmo tempo, pode até ser possível passar boa parte do trabalho para ela. Mas isso só pode ser realmente útil se você puder prever com precisão o número de bytes por palavra - ou pelo menos pode preencher cada palavra com espaços antes para uma contagem de bytes previsível, porque unblock come espaços à direita no final de cada bloco. / p>     

por 11.02.2015 / 23:14

Tags