extraindo linhas de texto de um arquivo longo

extraindo linhas de texto de um arquivo longo

Eu tenho o seguinte arquivo de texto:

#unimportant comment
#possible more unimportant comments
#info1 info2 info3 ,importantname1
importanttext1
#info1 info2 info3 ,importantname2
importanttext2
#info1 info2 info3 ,importantname3
importanttext3

Quero dividir cada arquivo em arquivos separados. Tudo que eu realmente preciso é extrair os URLs não comentados, preservar os comentários é opcional. Quero que cada arquivo seja nomeado como importantname1.txt ou o nome após a vírgula no final de cada linha de comentário anexada com .txt

então importantname1.txt teria o seguinte conteúdo:

importanttext1 

ou possivelmente

#info1 info2 info3 ,importantname1
importanttext1

então a linha seria extraída e salva com o nome do arquivo após o comentário e anexada com .txt neste caso nome do arquivo nome importante1.txt

É necessário fazer isso para cada conjunto de linhas no arquivo de exemplo. Preservar os comentários não é importante, mas preciso que seja compatível com scripts. Também preciso levar em conta um número desconhecido de linhas de comentários no cabeçalho. A linha de comentário sempre estará lá antes de cada linha importanttextX

Responder1

Tentar:

awk -F, '/^#/{f=$NF".txt";cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file

Exemplo

Aplicado à sua entrada de amostra:

$ awk -F, '/^#/{f=$NF".txt";cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file

Após a execução do procedimento acima, os seguintes arquivos estarão no diretório:

$ ls
file  importantname1.txt  importantname2.txt  importantname3.txt

O conteúdo dos novos arquivos é:

$ cat importantname1.txt 
#info1 info2 info3 ,importantname1
importanttext1
$ cat importantname2.txt 
#info1 info2 info3 ,importantname2
importanttext2
$ cat importantname3.txt 
#info1 info2 info3 ,importantname3
importanttext3

Como funciona

Awk lê o arquivo de entrada linha por linha. Nosso script classifica essas linhas como comentários ou não comentários. Para linhas de comentários, o nome do arquivo e o comentário são salvos. Para não comentários, um novo arquivo é criado e impresso

  • `-F,

    Isso diz ao awk para usar uma vírgula como separador de campos na entrada. Desta forma, o nome do arquivo sempre estará no último campo.

  • /^#/{f=$NF".txt";cmt=$0; next}

    Se uma linha começar com #, salvamos o último campo, $NF, mais .txtcomo um nome de arquivo f. Toda a linha de comentários é salva como arquivo cmt. Em seguida, dizemos ao awk para pular o restante dos comandos e pular para recomeçar a nextlinha.

  • printf "%s\n%s\n",cmt,$0 >f; close(f)

    Para linhas sem comentários, imprimimos o último comentário visto, cmte a linha atual, $0, no último nome do arquivo visto f. Em seguida, fechamos o identificador do arquivo f.

Proteção contra nomes de arquivos incorretos

Se os campos que serão usados ​​como nomes de arquivos contiverem /, o sistema operacional interpretará os nomes dos arquivos como incluindo diretórios. Para evitar isso, podemos substituir tudo /usando -o gsub(/\//, "-", f)seguinte:

awk -F, '/^#/{f=$NF".txt";gsub(/\//, "-", f); cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file

Responder2

Uma combinação de grepe csplitpoderia fazer o trabalho, a) grepexecutar ping em todas as linhas não comentadas mais a informação anterior e b) dividir a saída com base na linha de comentário de informações:

grep -v -B1 '^#' file | csplit -z - '/^#/' '{*}'

Ou seja, não -vextraia linhas que tenham um # no início, ^#mas uma linha precedendo tais linhas -B1. Em seguida, divida a entrada canalizada de entrada -em cada # no início de uma linha, ignore os arquivos vazios -ze faça isso com a maior freqüência possível {*}.

A renomeação teria que ser uma etapa separada ( csplitnomeia automaticamente o outpit como xx00, xx01 ... - altere pré e sufixo com as opções -fe -b, respectivamente)

#/bin/bash
for f in xx* ; do
   mv "$f" "$( sed -n '2p' "$f" )".txt
done

informação relacionada