Extraia strings entre tags e salve em um novo arquivo de texto

0

Eu preciso extrair strings de texto de um arquivo e colocá-las em um novo arquivo. Cada string está sempre entre o mesmo texto (tags).

Veja um exemplo (há centenas de blocos como este em que eu preciso que os dados sejam colocados em um arquivo):

1731 0 obj
<</Page 250/Type/Annot/Subtype/Highlight/Rotate 0/Rect[ 95.4715 347.644 337.068 362.041]/NM(929cd95c-f962-4fa3-b734-2e0e67d7b321)/T(iPad)/CreationDate(D:20160818145053Z00'00')/M(D:20160818145204Z00'00')/C[ 0.454902 0.501961 0.988235]/CA 1/QuadPoints[ 95.4715 362.041 337.068 362.041 95.4715 347.644 337.068 347.644]/Contents(EXAMPLE OF TEXT TO BE EXTRACTED)/F 4/Subj(Highlight)>>
endobj

Eu preciso extrair Page 250 e EXEMPLO DE TEXTO A SER EXTRAÍDO

Para o exemplo Página 250 , as tags relevantes parecem ser:

<</

e

/Type

Para o exemplo EXEMPLO DE TEXTO A SER EXTRAÍDO , as tags relevantes parecem ser:

/Contents(

e

)/F

Por fim, gostaria que as páginas e o texto correspondente fossem classificados em ordem crescente, mas eu poderia gerenciar isso em uma planilha.

Eu tentei usar algumas respostas de aqui , mas não consegui faça funcionar ...

Estou muito confortável com a linha de comando do Unix, mas conheço um pouco de Python e AppleScript

    
por pdeli 04.09.2016 / 00:19

2 respostas

1

com awk :

awk -F/ '$1=="<<" {i=$2; for(j=3;j<=NF;j++) \
         if($j~/^Contents/) split($j,a,"[()]"); print i " _ " a[2]}' file.txt
  • Definindo o separador de campo como / , se o primeiro campo for << , salvando o segundo campo como variável i a ser impresso posteriormente

  • Iterando o restante dos campos e se algum campo começar com Contents , então dividindo o campo em () para criar o array a , for(j=3;j<=NF;j++) if($j~/^Contents/) split($j,a,"[()]")

  • imprimindo a variável i e o segundo elemento da matriz a separando-os por _

Exemplo:

% cat file.txt                                                                                                        
1731 0 obj
<</Page 250/Type/Annot/Subtype/Highlight/Rotate 0/Rect[ 95.4715 347.644 337.068 362.041]/NM(929cd95c-f962-4fa3-b734-2e0e67d7b321)/T(iPad)/CreationDate(D:20160818145053Z00'00')/M(D:20160818145204Z00'00')/C[ 0.454902 0.501961 0.988235]/CA 1/QuadPoints[ 95.4715 362.041 337.068 362.041 95.4715 347.644 337.068 347.644]/Contents(EXAMPLE OF TEXT TO BE EXTRACTED)/F 4/Subj(Highlight)>>
endobj

% awk -F/ '$1=="<<" {i=$2; for(j=3;j<=NF;j++) if($j~/^Contents/) split($j,a,"[()]"); print i " _ " a[2]}' file.txt
Page 250 _ EXAMPLE OF TEXT TO BE EXTRACTED
    
por 04.09.2016 / 09:21
1

Eu adicionei o seu conteúdo de exemplo a um arquivo de disco chamado arquivo e mostrei o conteúdo do arquivo usando o cat comando . Então, usando awk on file eu essencialmente removo as partes que você está chamando tags e imprimo as duas peças de dados em uma guia delimitada formato. É isso que você está procurando?

$ cat file
1731 0 obj
<</Page 250/Type/Annot/Subtype/Highlight/Rotate 0/Rect[ 95.4715 347.644 337.068 362.041]/NM(929cd95c-f962-4fa3-b734-2e0e67d7b321)/T(iPad)/CreationDate(D:20160818145053Z00'00')/M(D:20160818145204Z00'00')/C[ 0.454902 0.501961 0.988235]/CA 1/QuadPoints[ 95.4715 362.041 337.068 362.041 95.4715 347.644 337.068 347.644]/Contents(EXAMPLE OF TEXT TO BE EXTRACTED)/F 4/Subj(Highlight)>>
endobj
$ awk '{sub(/\<\<\//, "")};{sub(/\/Type.*\/Contents\(/, "\t")};{sub(/\)\/F.*$/, "")};/Page [0-9]/{print}' file
Page 250    EXAMPLE OF TEXT TO BE EXTRACTED
$

O que o programa awk está fazendo:

  • /Page [0-9]/ está pesquisando por linhas que contêm, ou seja, "Página" um espaço, seguido por um número, por exemplo, Page 250 . Estou assumindo que EXAMPLE OF TEXT TO BE EXTRACTED não conterá esse padrão. Não que eu ache que isso importe, embora o código possa ser facilmente modificado para acomodar isso.

  • sub(/\<\<\//, "") strips: <</

  • sub(/\/Type.*\/Contents\(/, "\t") está substituindo tudo entre /Type e /Contents( por uma guia.
  • sub(/\)\/F.*$/, "") está retirando tudo de )/F para o final da linha.

Então, o que resta é o que é impresso. As duas partes de dados desejados separadas por uma guia.

Eu sei que isso não cobre todos os aspectos que você mencionou, mas seus outros requisitos não são claros o suficiente. É apenas um arquivo sua necessidade de processar ou multiplicar arquivos. Em ambos os casos, você quer todos os dados extraídos em um único arquivo e os dados classificados como exatamente, etc.

Então, se você pudesse esclarecer as coisas, eu provavelmente poderia escrever um script bash para encobri-lo.

Obviamente, com o programa awk que forneci, você pode apenas redirecionar a saída para um arquivo de saída e continuar a processá-lo com sort comando . awk pode fazer a classificação também, no entanto, obter os dados de destino em uma linha de comando era o que eu poderia oferecer com awk , neste ponto.

    
por 04.09.2016 / 08:42