Concatene todos os comentários sobre arquivos de origem em uma árvore de diretórios

4

Estou trabalhando em vários projetos envolvendo códigos em Fortran. Eles estão em uma árvore de diretórios envolvendo 10 a 20 pastas, cada um dos códigos está em uma pasta 'src'.

O que estou procurando é um comando simples que eu possa executar na raiz do arborescence para ir buscar todas as informações relevantes sobre os programas. Esta informação é comentada no cabeçalho dos arquivos .f ou .f90, mas é claro que pode ser executada em um número diferente de linhas em cada arquivo.

Uma dificuldade é que nem sempre está no topo do arquivo, já que às vezes há módulos primeiro. Mas a informação sempre lembra o nome do arquivo, ou pelo menos contém a palavra 'main'.

Mais precisamente, digamos que a arborescência é a seguinte:

/
|-folder1/
     |-program1.f
|-folder2/
     |-program2.f90

Em program1.f , preciso do seguinte bloco:

c
c program1 does the following
c blah blah
c

(isso pode ser um C maiúsculo)

e em program2.f90 preciso do seguinte:

!
! program2 does the following
! blah blah
!

Talvez exista uma expressão regular que possa ser usada para buscar o bloco de aviso completo?

    
por bela83 21.03.2014 / 11:00

2 respostas

2

Você pode experimentar este comando. Pode precisar de ajustes para o layout específico dos comentários que você quer (contra os que você não quer).

find . -type f -regex ".*\.[fF]\(90\)?" -exec awk '/^[Cc!]\ *program/{f=1} f{if(/^[^Cc!]/) exit; print}' {} \;

Isso localizará todos os arquivos Fortran comumente chamados em sua árvore de diretórios e imprimirá o primeiro bloco de comentários que começa com ! program , C program ou c program e imprime a totalidade desse bloco de comentário e apenas esse bloco de comentário. Eu escolhi esses regexs com base em seus blocos de comentário de amostra.

Se você precisar disso, me avise nos comentários ou podemos configurar uma sala de bate-papo para descobrir isso. Isso deve começar com o que você quer embora. Se os seus comentários nem sempre começarem com program , pode tentar

find . -type f -regex ".*\.[fF]\(90\)?" -exec awk '/^[Cc!]\ *$/{f=1} f{if(/^[^Cc!]/) exit; print}' {} \;

que, em vez disso, iniciará a partida na primeira linha com apenas um caractere de comentário e, opcionalmente, espaços em branco na linha.

Observação Essas correspondências dependem do caractere de comentário que está na coluna 1. Se você tiver arquivos de forma livre com o bloco de comentários que precisa iniciar em uma coluna diferente (não comum para comentários de nível superior), estes não funcionam.

Como isso funciona:

find . -type f -regex ".*\.[fF]\(90\)?"

pesquisa em seu diretório atual (altere . para um caminho absoluto para poder executá-lo em qualquer lugar) de forma recursiva para qualquer arquivo chamado *.f , *.F , *.f90 ou *.F90 . Em seguida, executa:

awk '/^[Cc!]\ *program/{f=1} f{if(/^[^Cc!]/) exit; print}' {} \;

em cada arquivo encontrado. Vamos dividir isso:

/^[Cc!]\ *program/{f=1}

Isso corresponde à primeira linha que começa com um caractere de comentário C , c ou ! , contém qualquer número de espaços e, em seguida, a palavra program . Isso corresponde à primeira linha real de seus blocos de comentários de amostra. Awk imprime esta linha e continua as linhas de impressão até

if(/^[^Cc!]/) exit;

é correspondido. Isso corresponde à primeira linha subsequente que não inicia com um caractere de comentário. Neste ponto, o awk sai e o próximo arquivo é processado.

    
por 24.03.2014 / 23:46
1

Se a informação que você precisa é de linhas independentes, então% recursivagrep é o caminho a percorrer. Por exemplo, se você quiser encontrar todas as linhas de comentário, algo como grep -r ^C pode resolver o problema. (Eu estou supondo que a sintaxe comentário aqui. Eu sou old-school, mas não que old-school).

Se você precisa de uma lógica mais complexa, por exemplo "obtenha todas as linhas no primeiro bloco de linhas que começam com BLAH, mas pare após a primeira linha não BLAH", então você deve chamar um comando em cada arquivo, provavelmente sed ou awk . Por isso, find é seu amigo: normalmente você faria algo como

find -exec awk '<AWK expression extracting what you need>' {} \;

    
por 21.03.2014 / 11:44