Acesse linhas individuais de um arquivo de texto e crie um arquivo de texto separado com esse nome

6

Eu tenho dois arquivos de texto (digamos text1.txt e text 2.txt ) ambos com o mesmo número de linhas. Ex. text1.txt contém 4 entradas

0127H
0132H
0982H
1772H

text2.txt contém 4 entradas

stev
mary
beautiful
ugly

Agora, minha tarefa é criar 4 arquivos de texto como

  • 0127H.txt para conter stev

  • 0132H.txt para conter mary

  • 0982H.txt para conter beautiful

  • 1772H.txt para conter ugly

Ou seja. a primeira linha de text1.txt deve ser um nome de arquivo e a entrada correspondente será a primeira linha de text2.txt .

Eu gentilmente peço que você me ajude a se livrar da questão levantada.

    
por Pradeep Rangan 01.05.2015 / 11:08

8 respostas

3

Com awk , você pode fazer:

awk 'FNR == NR {filename[FNR] = $0 ".txt"} FNR != NR {print > filename[FNR]}' file1 file2
  • FNR == NR testa se estamos lendo o primeiro arquivo. Se for esse o caso, salvamos a linha em uma matriz.
  • Quando lemos o segundo arquivo, procuramos o valor da matriz correspondente e o usamos como o arquivo de saída.
por muru 01.05.2015 / 11:52
2

O seguinte one-liner fará o que você precisa:

bash -c "$(paste text1.txt text2.txt | awk '{print "echo "$2">"$1".txt"}')"
    
por Sylvain Pineau 01.05.2015 / 11:47
2

Outra opção em python:

#!/usr/bin/env python3
import sys

lines = lambda f: open(f).read().splitlines()
content = lines(sys.argv[2])

for i, item in enumerate(lines(sys.argv[1])):
    open(item+".txt", "wt").write(content[i])

Isso criará os arquivos indicados no diretório em que você executa o script

  • Salve como combine.py
  • execute-o com o comando:

    python3 /path/to/combine.py <file1> <file2>
    

Editar

Como sugerido por @queueoverflow, usando a opção zip (muito legal, ainda mais curta):

#!/usr/bin/env python3
import sys

lines = lambda f: open(f).read().splitlines()
for item, content in zip(lines(sys.argv[1]), lines(sys.argv[2])):
    open(item+".txt", "wt").write(content)

OU

Apenas por diversão; incluindo o sys.argv[n] na função lambda, reduzindo um pouco mais:

#!/usr/bin/env python3
import sys

lines = lambda n: open(sys.argv[n]).read().splitlines()
[open(f+".txt", "wt").write(c) for f, c in list(zip(lines(1), lines(2)))]
    
por Jacob Vlijm 01.05.2015 / 16:19
1

Isso funcionou para mim:

c=1; while read f; do sed -n "${c}p" text2.txt >"$f.txt"; ((c++)); done <text1.txt

Ele é iterado por todas as linhas no arquivo text1.txt . Em seguida, para cada linha sed extrai a linha correspondente no arquivo text2.txt e grava no arquivo com .txt anexado.

    
por chaos 01.05.2015 / 11:48
0

Eu posso fazer isso com o seguinte script:

#!/bin/bash

FILENAME="$1"
count=0
while read LINE
do
  let count++
  sed -n "$count"p text2 > "$LINE".txt
done < "$FILENAME"
    
por Ron 01.05.2015 / 12:19
0

Você pode fazer isso em bash :

IFS=$'\n'
a=($(<text1.txt))
i=0
while read -r line; do
  echo "${line}" > "${a[i++]}"
done < text2.txt

A designação IFS informa bash para tratar apenas nova linha como o delimitador de palavras. Se você não quiser que essa configuração afete seu shell em execução, convém iniciar uma nova instância de bash para tudo isso ou redefinir IFS depois para o padrão usando IFS=$' \t\n' .

A próxima linha tem duas partes. a=( 0127H 0132H 0982H 1772H ) tornaria a uma matriz com quatro entradas. Mas, em vez de listar as entradas na íntegra, substituímos o conteúdo do arquivo lá. $(…) geralmente executa um comando e se expande para sua saída, mas com um < inicial, ele se comporta quase como se o comando fosse cat , ou seja, ele se expande para o conteúdo desse arquivo. A saída desse arquivo é dividida em palavras que correspondem a IFS , portanto, as linhas que contêm espaço em branco terminam em um único elemento de matriz.

Em seguida, percorremos as linhas de text2.txt e usamos o contador i para identificar o elemento correspondente de text1.txt . Também poderíamos carregar text2.txt como uma matriz e, em seguida, iterar sobre ambas as matrizes em paralelo, particularmente depois de verificar se seus comprimentos estão de acordo.

IFS=$'\n'
a=($(<text1.txt))
b=($(<text2.txt))
if [[ ${#a[@]} -ne ${#b[@]} ]]; then
  echo "Length mismatch" >& 2
else
  for ((i=0; i<${#a[@]}; ++i)); do
    echo "${b[i]}" > "${a[i]}"
  done
fi
    
por MvG 01.05.2015 / 21:50
0

Aqui está minha tentativa nessa tarefa:

Passo 1 - crie uma lista de todos os arquivos de texto que você deseja ter uma palavra. Nomeado meu list e um perline listado text1, text2, text3 e text4

Passo 2 - Crie uma lista de palavras, uma por linha. O meu é chamado word

Etapa 3 - execute o seguinte comando: pr -m -t words list | awk '{x=$2; print $1>x}'

Agora, é claro, não é uma linha direta, mas funcionou para mim. Minha lista de palavras era one two three four e agora text1 tem one , text2 tem two e assim por diante

Editar :

Aqui está minha tentativa grosseira de endereçar espaços entre palavras no arquivo words: translate \n para outro caractere e então usar esse caractere como delimitador no awk. Eu testei isso com df | tr '\n' '@' | awk -F '@' '{for (i=1;i<5;i++) print $i > "file"i".txt" }'

O resultado é que eu tenho 4 arquivos diferentes, com 4 linhas consecutivas do comando df . Substitua df por cat words . Aqui está o resultado

E sim, esse método não é perfeito; e se uma linha contiver @ no meio dela ou no final. Mas este método é flexível - @ pode ser substituído por outra coisa. Além disso, o usuário provavelmente deve estar ciente ao tentar processar arquivos de texto como eles são delimitados; bom exemplo é /etc/passwd , onde os campos são separados por : , e ninguém cobrado cegamente para processar esse arquivo, certo?

    
por Sergiy Kolodyazhnyy 02.05.2015 / 22:54
0

Salve o script python abaixo como files.py ou similar. Você pode encontrá-lo aqui

#!/usr/bin/python3

# -*- coding: utf-8 -*-
# Copyright © 2015 Martin Ueding <[email protected]>    
# Licensed under The MIT License

import argparse


def main():

    options = _parse_args()
    with open(options.first) as f:    
        lines1 = [s.strip() for s in f.readlines()]    
    with open(options.second) as f:    
        lines2 = f.readlines()    
    for first, second in zip(lines1, lines2):    
        with open(first + '.txt', 'w') as f:    
            f.write(second)


def _parse_args():    
    '''    
    Parses the command line arguments.            
    :return: Namespace with arguments.    
    :rtype: Namespace    
    '''

    parser = argparse.ArgumentParser(description='')    
    parser.add_argument('first')    
    parser.add_argument('second')    
    options = parser.parse_args()             
    return options        


if __name__ == '__main__':    
    main()

Então você pode começar com

python3 files.py text1.txt text2.txt

e irá gerar todos os arquivos que você quiser.

Vantagens desta solução:

  • Funciona se as linhas nos arquivos tiverem espaços ou outros caracteres tratados especiais no shell.
  • O código é legível sem conhecer um monte de armadilhas no Bash .
  • Caso não haja parâmetros suficientes passados na linha de comando, você receberá uma mensagem de erro legível e chamá-la com -h ou --help também funcionará bem.
  • Ele pode lidar com quebras de linha no estilo DOS e Mac OS ( \n\r e \r ).
  • O script Python até seria executado no Windows.
  • Ele não vaza descritores de arquivos, pois usa gerenciadores de contexto ( with …: ).
por Martin Ueding 01.05.2015 / 11:16