Como posso capitalizar letras antes de um determinado caractere? (^)

5

Gostaria de converter isso:

foo^bar
ba^rfoo
oofrab
raboof^

Para isso:

FOObar
BArfoo
oofrab
RABOOF

Qualquer coisa antes do "^" (ou outro caracter especial se ficar mais fácil) é capitalizado

Além disso, a remoção do "^" também não é necessária se facilitar.

    
por TuxForLife 11.05.2015 / 05:31

8 respostas

8

Usando o GNU sed (padrão do Ubuntu) (graças ao pabouk para a sugestão da opção -r ):

< inputfile sed -r 's/^(.*)\^/\U\E/' > out

Usando perl (graças a Oli pelo regex abreviado):

< inputfile perl -pe 's/^(.*)\^/\U\E/' > out

Resumo do comando # 1 :

  • < inputfile : redireciona o conteúdo de inputfile para stdin
  • -r : permite o uso de regexes estendidos
  • > out : redireciona o conteúdo de stdout para out

Divisão do comando # 2 :

  • < inputfile : redireciona o conteúdo de inputfile para stdin
  • > out : redireciona o conteúdo de stdout para out

Divisão do Regex :

  • s : realiza uma substituição
  • / : inicia o regex
  • ^ : corresponde ao início da linha
  • ( : inicia o primeiro grupo de captura
  • .* : corresponde a qualquer número de caracteres
  • ) : pára o primeiro grupo de captura
  • \^ : corresponde a um caractere ^
  • / : pára a regex / inicia a substituição
  • \U : inicia a conversão para maiúsculas
  • : substitui pelo primeiro grupo de captura
  • \E : para de converter para maiúsculas
  • / : interrompe a substituição
por kos 11.05.2015 / 05:38
5

Usando vim :

vim -es '+g/\^/normal gUf^' +wq foo
  • O -es ativa o venerável modo ex e silencia o vim (principalmente).
  • + é usado para fornecer comandos vim como argumentos de linha de comando.
  • g/\^/ - executa o comando em todas as linhas correspondentes a /\^/
  • normal - executa o resto do comando como uma ação no modo normal.
  • gUf^ - converter em maiúsculas ( gU ) até ^ ( f^ ). Ao usar um intervalo g/.../ neste caso, o cursor é colocado no início de cada linha antes de executar o comando.
  • Em seguida, salve e saia ( wq ).

f procura o primeiro ^ , portanto, as linhas com vários ^ teriam apenas o campo convertido. Não há movimento simples para encontrar o último ^ . Você pode tentar ir para o final da linha e pesquisar para trás ( $F^ ), mas isso falhará se ^ for o último caractere. Então, você precisaria fazer isso em duas etapas:

vim -es '+g/\^./norm $F^gU0' '+g/\^$/norm gU$' +wq foo
    
por muru 11.05.2015 / 11:41
3

Eu definiria ^ como separador de campo em awk em maiúsculas no primeiro campo:

$ awk 'BEGIN{FS="^"; OFS=""} NF>1{$1=toupper($1)}1' file
FOObar
BArfoo
oofrab
RABOOF

Ao dizer OFS="" , definimos o separador do campo de saída como a string vazia, para que o ^ seja removido. Se isso não for necessário, awk -F"^" '{$1=toupper($1)}1' file sozinho conseguiria; ele converte todos os ^ em espaços.

Note que usamos NF>1 para realizar a maiúscula caso haja pelo menos um ^ .

    
por fedorqui 11.05.2015 / 11:21
2

EDITAR

Então, depois de cerca de uma hora e meia, eu descobri isso:

awk -F' ' '{ gsub(/\^/,"@ "); for (i=1;i<=NF;i++){ if($i ~ /\@/) $i = toupper($i);};gsub("@ ","");gsub("@",""); print   }  ' removecharsfile 

Ideias básicas:

  • livre-se de ^ e substitua-o por @ mais espaço
  • Tratar espaço como delimitador de campo; agora temos campos para brincar com
  • para que o loop percorra cada campo em cada linha e verifique se há @ caractere.
  • se houver @ caractere, converta esse campo para superior. Por que $ i = toupper ($ i)? Porque senão ele não fica armazenado em lugar algum
  • depois que o loop for concluído, livre-se de @ + space e @ no final dos campos.
  • imprima tudo

Talvez uma abordagem melhor para escrever tudo isso em uma linha seja colocá-lo em um arquivo (bem organizado abaixo) e executá-lo com o awk, assim como awk -f awkscript theinputfile

# awk script to capitalize
# whatever comes before caret(^)


{
  gsub (/\^/, "@ ");
  for (i = 1; i <= NF; i++)
    {
      if ($i ~ /\@/)
        $i = toupper ($i);
    };
  gsub ("@ ", "");
  gsub ("@", "");
  print

}

E aqui está em ação:

POSTIGOORIGINAL

Eucontribuireicomminhaprópriaversãodecódigocomoawk:

awk-F'^''{printtoupper($1)$2}'thefile

E,claro,vocêpoderedirecionarasaídacom>output.txtEaquiestáemação:

    
por Sergiy Kolodyazhnyy 11.05.2015 / 06:14
2

Bash também pode fazer isso, então eu vou dar uma resposta bash no mix.

#bash
while IFS= read -r line; do
    if [[ $line = *^* ]]; then
        tmp=${line%%^*} 
        line=${tmp^^}${line#*^}
    fi
    printf '%s\n' "$line"
done < inputfile > outptufile

Isso é apenas iterar o arquivo de entrada linha a linha ( BashFAQ 1 ) e usar expansões de parâmetros para fazer o divisão e maiúsculas ( BashFAQ 73 ).

    
por geirha 11.05.2015 / 11:12
2

Através do python3,

Sem usar re module,

with open(file) as f:
    for line in f:
        if '^' in line:
            m = line.strip().split('^')
            print(m[0].upper() + m[1])
        else:
            print(line, end="") 

Com o uso do módulo re .

import re
with open(file) as f:
    for line in f:
        print(re.sub(r'(.*)\^', lambda m: m.group(1).upper(), line.strip()))

Substitua file nos scripts acima pelo caminho real do arquivo. E execute o script usando o comando python3 .

    
por Avinash Raj 11.05.2015 / 12:53
1

Outra versão awk :

awk '{ a=$_; ismatch=sub(/\^.*/, "", a); b=gensub(/.*\^(.*)/, "\1", "", $_); if(ismatch==1) { print toupper(a) b} else { print b} }' testdata

legível por humanos;)

awk '{
  a=$_;
  ismatch=sub(/\^.*/, "", a);
  b=gensub(/.*\^(.*)/, "\1", "", $_);
  if(ismatch==1) {
    print toupper(a) b
  }
  else {
     print b
  }
}' testdata
    
por A.B. 11.05.2015 / 11:42
1

Outra abordagem python :

#!/usr/bin/env python2
with open('/path/to/file.txt') as f:
    for line in f:
        if '^' in line:
            index = line.find('^')
            print line[:index].upper() + line[index+1:].rstrip()
        else:
            print line.rstrip()

Saída:

FOObar
BArfoo
oofrab
RABOOF
  • index = line.find('^') contém o índice do caractere ^

  • line[:index].upper() imprime os caracteres antes de index ( ^ ) em letras maiúsculas ( upper() )

  • line[index+1:] imprime os caracteres depois de ^ literalmente

  • rstrip() removerá as novas linhas iniciais adicionadas por print por padrão.

EDITAR:

Agora, se você tiver um arquivo como este (vários ^ ):

foo^bar^spam
ba^rfoo^egg
oofrab
raboof^spamegg

e você quer fazer como:

FOOBARspam
BARFOOegg
oofrab
RABOOFspamegg

Nesse caso, você pode usar:

#!/usr/bin/env python2
with open('/path/to/file.txt') as f:
    for line in f:
        if '^' in line:
            index = line.rfind('^')
            print line[:index].upper().replace('^', '') + line[index+1:].rstrip()
        else:
            print line.rstrip()

Saída:

FOOBARspam
BARFOOegg
oofrab
RABOOFspamegg

Apenas as substituições são rfind('^') em vez de find('^') , que encontrarão o índice de% mais^ e replace('^', '') substituirá todos os ^ s por espaços em branco.

    
por heemayl 11.05.2015 / 19:53