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.txt
como um nome de arquivof
. Toda a linha de comentários é salva como arquivocmt
. Em seguida, dizemos ao awk para pular o restante dos comandos e pular para recomeçar anext
linha.printf "%s\n%s\n",cmt,$0 >f; close(f)
Para linhas sem comentários, imprimimos o último comentário visto,
cmt
e a linha atual,$0
, no último nome do arquivo vistof
. Em seguida, fechamos o identificador do arquivof
.
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 grep
e csplit
poderia fazer o trabalho, a) grep
executar 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 -v
extraia 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 -z
e faça isso com a maior freqüência possível {*}
.
A renomeação teria que ser uma etapa separada ( csplit
nomeia automaticamente o outpit como xx00, xx01 ... - altere pré e sufixo com as opções -f
e -b
, respectivamente)
#/bin/bash
for f in xx* ; do
mv "$f" "$( sed -n '2p' "$f" )".txt
done