Como copiar seletivamente detalhes de um arquivo e colá-los em um novo arquivo?

11

Eu tenho um arquivo que contém meus dados pessoais (.txt). Como posso, através do terminal, copiar apenas alguns detalhes do arquivo e colocá-los em um novo .txtarquivo?

Por exemplo, se este for o conteúdo do arquivo:

name : farah age : 23 phone number : 0123 education : degree

como posso copiar apenas idade e número de telefone e enviá-los para um novo .txtarquivo?

MsWanie
fonte
2
Depende do que você deseja copiar para o novo arquivo. Deseja que as primeiras linhas, as últimas linhas, contenham uma string, sem uma string, linhas entre duas strings? Existem ferramentas para fazer tudo isso, mas precisamos saber o que você deseja fazer.
Arcege 31/08/11

Respostas:

7

Existem várias maneiras de fazer isso. Se o seu arquivo tiver alguma estrutura conhecida, você poderá usá-lo grep. O grepcomando procura em um arquivo por uma frase específica e retorna linhas que correspondem a essa frase. Portanto, se seu arquivo parecer

Nome: Sally

Data de nascimento: 7.31.76

Endereço: 1234 Main St.

SSN: 123-45-6789

você pode correr grep Name info.txte ele retornará Name: Sally. Você pode redirecionar a saída para outro arquivo. Então chamando

grep Name info.txt > info2.txt

produzirá a linha para o novo arquivo info2.txt. Se você deseja acrescentar novas linhas, pode fazer

grep Address info.txt >> info2.txt

caso contrário, o arquivo será substituído.

Você também pode aprender a usar um editor de texto de linha de comando como o vim.

Kris Harper
fonte
2

Você pode usar o grep para procurar uma expressão regular em details.txt e redirecionar o resultado para o novo arquivo.

Se todas as linhas que você deseja copiar têm algo em comum, as outras linhas não podem ser usadas:

grep "string in common" details.txt > new.txt

Caso contrário, você terá que procurar cada linha que deseja copiar, ainda usando grep, e anexá-las ao new.txt usando >>no lugar de >.

danjjl
fonte
1

Existem também editores que trabalham no terminal, por exemplo, nano, vi e emacs.

Se você estiver usando uma interface gráfica do usuário em sua máquina local e um terminal em uma máquina remota, também poderá usar o mouse para copiar e colar de uma janela / guia do terminal para uma segunda.

elmicha
fonte
1

Supondo que o arquivo de entrada details.txtcontenha:

name: farah
age: 23
phone number: 0123
education: degree

você pode selecionar as linhas "nome" e "telefone" por grep estendido e redirecionar a saída para new.txt:

grep -E "age:|phone number:" details.txt > new.txt

Isso produzirá new.txt com:

age: 23
phone number: 0123

Como funciona:

Grep imprime apenas linhas correspondentes. As -Eopções ativaram o regexp estendido, que oferece a possibilidade de usar |(alternativa). Lembre-se de citar o padrão inteiro, por isso |será interpretado pelo grep. Caso contrário, o shell tentará interpretar. Você não quer isso aqui.

Michał Šrajer
fonte
1

O arquivo que você mostrou tem todos os detalhes em uma linha:

name : farah age : 23 phone number : 0123 education : degree

Eu assumi que você pode codificar age :etc no comando, mas o texto a seguir varia, e os detalhes podem não estar na ordem especificada ou serem contíguos.

Você pode extrair partes da linha com grepo -osinalizador de. Isso imprime apenas a parte correspondente, em vez da linha inteira.

Se você deseja incluir as peças age :e phone number :, pode usar o -esinalizador para especificar várias correspondências ou alternância.

$ grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file
age : 23
phone number : 0123

A expressão [^ ]*significa qualquer número de caracteres que não são um espaço, portanto, corresponde aos caracteres após age :o próximo espaço.

Substitua filepelo nome do arquivo que contém seus detalhes. Você pode gravar o novo arquivo redirecionando a saída para um novo arquivo com o >operador, assim:

grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file > outfile

Ao fazer isso, você não verá nenhuma saída. Você deve verificar a saída primeiro e depois adicionar o redirecionamento.

Aqui está o exemplo com alternância. Usamos a -Eflag para dizer greppara usar regex estendido. A sintaxe é (pattern1|pattern2)- isso corresponde pattern1e / ou pattern2. Se um for encontrado, ele será impresso (independentemente de o outro ser encontrado ou não). Agora estou usando o +significado de pelo menos um dos caracteres anteriores, em vez de *significar zero ou mais do caractere anterior. Nesse contexto, os dois funcionam igualmente bem.

$ grep -Eo '(age : [^ ]+|phone number : [^ ]+)' file
age : 23 
phone number : 0123 

Se você quiser omitir as partes age :e phone number:, poderá usar o -Psinalizador para solicitar o grepuso de expressões regulares compatíveis com Perl. Isso suporta alternância e também uma maneira de corresponder texto após um determinado padrão:

$ grep -Po '(age : \K[^ ]+|phone number : \K[^ ]+)' file
23
0123

Se você deseja formatar o texto de maneira diferente, pode usar sed, por exemplo:

$ sed -r 's/.*(age) : ([^ ]*).*(phone number) : ([^ ]*).*/\1:\2 | \3:\4/' file
age:23 | phone number:0123

Isso depende da agevinda anterior phone number, portanto, ajuste de acordo se não for esse o caso. Se você não pode confiar no pedido, pode usar este comando muito complicado:

$ sed -r 's/(.*)(phone number : [^ ]+)(.*) .*/\2 \1\4/; s/(phone number) : ([^ ]+) .*(age) : ([^ ]+).*/\1: \2 | \3: \4/' file
phone number: 0123 | age: 23

Isso reorganiza a linha para que a phone number :seção seja a primeira em cada linha e, em seguida, faz uma segunda substituição para selecionar os detalhes desejados. Devo a técnica usada aqui a esta resposta por muru .

Notas sobre sedcomandos não cobertos por explicações anteriores

  • -ruse regex estendido para comandos mais legíveis (o GNU sedentende -Ecom o mesmo significado)
  • s/old/new/substitua oldpornew
  • (pattern)salva patternpara fazer referência mais tarde, com \1ou \2etc (correspondente à ordem da esquerda para a direita na qual os grupos de captura ocorrem - observe que sedconterão apenas 7 deles!).
  • .qualquer caractere, portanto, .*representa qualquer número de caracteres.
  • ; separa comandos, como no shell.
Zanna
fonte