Como posso dividir um arquivo de texto baseado no conteúdo em vários arquivos de texto?

4

Eu tenho um arquivo de texto chamado CAMS.txt que contém o seguinte:

4153999999999991
4153999999999992
4153999999999993
4153999999999994
4801999999999991
4801999999999992
4801999999999993

Eu gostaria de dividir o arquivo CAMS.txt em 2 arquivos - CAMS1.txt e CAMS2.txt. Seu conteúdo é o seguinte

CAMS1.txt

4153999999999991
4153999999999992
4153999999999993
4153999999999994

CAMS2.txt

4801999999999991
4801999999999992
4801999999999993

Ele está realmente dividindo o arquivo com base nos quatro primeiros dígitos do arquivo CAMS.txt original. Será sempre 4153 e 4801. Sou novo no mundo unix =)

    
por user65998 24.04.2014 / 00:08

3 respostas

5

awk '/^4153/ {print >"CAMS1.TXT"; next} {print >"CAMS2.TXT"}' CAMS.TXT

Existem outras maneiras de fazer isso, outra seria usar dois comandos do grep

grep "^4153" CAMS.TXT > CAMS1.TXT
grep -v "^4153" CAMS.TXT > CAMS2.TXT

Isso é menos eficiente, mas mais fácil de digitar, depois que o primeiro grep é feito, você o recupera do histórico do shell (usando a tecla de seta "para cima") e faz algumas alterações. Claro que o arquivo é lido duas vezes, então não faça isso se for grande.

    
por 24.04.2014 / 00:15
4

Para este caso específico em que você já conhece o texto, você pode fazer algo como

while read line; do 
    [[ $line =~ ^4153 ]] && 
        printf "%s\n" "$line" >> CAMS1.TXT || 
        printf "%s\n" "$line" >> CAMS2.TXT 
done < CAMS.TXT 

Isso lê cada linha de CAMS.TXT na variável $line e, em seguida, se $line começar com 4153, ela será impressa no CAMS1 e, caso contrário, será impressa no CAMS2.

Como alternativa, você pode imprimir cada linha para erro padrão ou saída padrão, dependendo de quais são os primeiros números e redirecionar a saída do comando de acordo. Por exemplo:

perl -ne '/^4153/ ? print STDOUT : print STDERR' CAMS.TXT >CAMS1.TXT 2>CAMS2.TXT 

Se você não sabe o que o texto será, você pode simplesmente escrever cada linha em um arquivo cujo nome são os primeiros 4 caracteres da linha:

awk '{print >> substr($1,1,4)}' CAMS.TXT 

Os itens acima criarão dois arquivos, 4153 e 4801 , cada um contendo as linhas esperadas. Isso tem a vantagem de trabalhar com vários padrões diferentes.

    
por 24.04.2014 / 01:31
2

Aqui está uma pura variante bash em a solução mais geral de terdon .

while read line; do 
  echo "$line" >> "${line:0:4}.txt"
done < CAMS.txt

Os arquivos resultantes serão nomeados de acordo com os primeiros quatro caracteres em cada linha, por exemplo, 4153.txt e 4801.txt para a entrada de amostra.

O fragmento a seguir pode ser usado para renomear em lote os arquivos resultantes para CAMS1.txt , CAMS2.txt etc. (supondo que os primeiros quatro caracteres de cada linha na entrada original fossem de fato dígitos).

i=1
for file in [0-9][0-9][0-9][0-9].txt; do
  mv "$file" "CAMS$(( i++ )).txt"
done

Isso depende da observação de que os números no arquivo de entrada original estão em ordem crescente, e a numeração dos arquivos dos arquivos de saída de amostra corresponde a essa ordenação.

Explicação:

while read line; do 
  ...
done < CAMS.txt

Iterar o arquivo CAMS.txt , lendo cada linha, por sua vez, na variável line .

echo "$line" >> "${line:0:4}.txt"

Acrescenta a linha atualmente sendo processada a um arquivo, cujo nome é obtido dos quatro primeiros caracteres da linha atual.

i=1

Atribua o valor 1 à variável i .

for file in [0-9][0-9][0-9][0-9].txt; do
  ...
done

Iterar arquivos no diretório atual que tenham quatro dígitos em seu nome e terminem com a extensão .txt . O [0-9][0-9][0-9][0-9].txt no snippet acima é chamado de shell glob . Esse recurso pode ser usado para corresponder ou expandir tipos específicos de padrões, neste caso, nomes de arquivos.

mv "$file" "CAMS$(( i++ )).txt"

Renomeie o file atualmente sendo processado. O nome do arquivo de destino, "CAMS$(( i++ )).txt ", consiste no prefixo CAMS concatenado com o valor atual da variável i . A variável i é, ao mesmo tempo, incrementada dentro de bash expressão aritmética , conforme indicado pela sintaxe (( ... )) , usando o operador de incremento de postfix ++ . % before $ faz com que o valor da expressão, neste caso o valor de (( ... )) antes do incremento, seja expandido para a string indicando o nome do arquivo de destino. Por fim, o sufixo i é anexado ao nome do arquivo de destino.

    
por 24.04.2014 / 06:55