Como extrair dois números de duas strings e calcular a diferença no Bash?

1

Eu tenho um arquivo de texto que contém (entre outras) as seguintes linhas:

{chapter}{{1}Einleitung}{27}{chapter.1}  
{chapter}{{2}Grundlagen}{35}{chapter.2}

Como posso

  • obtenha as duas linhas desse arquivo de texto (elas sempre conterão }Einleitung resp. }Grundlagen} e
  • extraia os números de 2 páginas (neste caso, 27 e 35),
  • calcule a diferença 35-27 = 8 e
  • salve a diferença ( 8 ) dos dois números em uma variável

Talvez com um script bash no Mac OS X?

    
por MostlyHarmless 12.12.2011 / 12:31

4 respostas

3

Não sei se o Mac OS X tem o awk. Em caso afirmativo, isso deve funcionar:

Isso deve funcionar:

DIFFERENZ=$(awk 'BEGIN {
  FS="[{}]+"
 } {
  if ($4=="Einleitung")
   EINLEITUNG=$5
  if ($4=="Grundlagen")
   GRUNDLAGEN=$5
 } END {
   print GRUNDLAGEN-EINLEITUNG
 }' textfile)

Como funciona:

  • FS="[{}]+" define o separador de campos para qualquer combinação de chaves.
  • $4 refere-se ao terceiro registrado na linha (separado por chaves).
  • DIFFERENZ=$(...) avalia o comando ... e armazena a saída em DIFFERENZ .
por 12.12.2011 / 12:58
3

calc.awk:

BEGIN {
    FS="}{";           # split lines by '}{'
    e=0;               # set variable 'e' to 0
    g=0;               # set variable 'g' to 0
}

/Einleitung/ { e=$3; } # 'Einleitung' matches, extract the page
/Grundlagen/ { g=$3;}  # 'Grundlagen' matches, extract the page

END {
    print g-e;         # print difference
}

você pode ligar por:

$> awk -f calc.awk < in.txt

imprimirá 8 . você poderia armazenar esse número em uma variável bash assim:

$> nr='awk -f calc.awk < in.txt' 

se você precisar de mais informações, você também pode reescrever calc.awk para não ser um arquivo separado, mas uma linha:

$> nr='awk 'BEGIN{FS="}{";g=0;e=0}/Einleitung/{e=$3;}/Grundlagen/{g=$3;}END{print g-e;}' < in.txt'
    
por 12.12.2011 / 12:57
1

Pure bash 4.x, e mostra as diferenças para cada capítulo:

unset page_last title_last page_cur title_cur
re='\{chapter\}\{\{[[:digit:]]+\}([^}]+)\}\{([[:digit:]]+)\}'
while read -r line; do
    if [[ $line =~ $re ]]; then
        title_cur=${BASH_REMATCH[1]} page_cur=${BASH_REMATCH[2]}
        diff=$((page_cur-page_last))
        echo "${diff} pages between \"${title_last}\" and \"${title_cur}\""
        title_last=$title_cur page_last=$page_cur
    fi
done < "$myfile"
    
por 12.12.2011 / 13:23
0
$ DIFFERENCE=$(( $( cat FILENAME | grep Grundlagen | head -n1 | cut -c26-27 ) - $( cat FILENAME | grep Einleitung  | head -n1 | cut -c26-27 ) ))
$ echo $DIFFERENCE
8

Isso requer que as linhas sempre sejam exatamente assim (ou seja, sem título diferente), por causa do cut .

    
por 12.12.2011 / 12:57