Como extrair dois números de duas seqüências e calcular a diferença no Bash?

1

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

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

Como posso

  • obtenha as 2 linhas deste arquivo de texto (elas sempre conterão }Einleitung resp. }Grundlagen} e
  • extrair os números de 2 páginas (neste caso, 27 e 35),
  • calcular 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?

MostlyHarmless
fonte
var=$({ grep -Eo '(Einleitung|Grundlagen)\}.[0-9]+.'|sort -r|tr '\n' ' '| tr -d -c '0-9 '|awk '{print $1 - $2}'; }</tmp/inputfile)
artistoex

Respostas:

3

Eu não sei se o Mac OS X tem awk. Se isso acontecer, 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 campo para qualquer combinação de chaves.
  • $4 refere-se ao terceiro arquivado na linha (separado por chaves).
  • DIFFERENZ=$(...) avalia o comando ... e armazena a saída em DIFFERENZ.
Dennis
fonte
obrigado, isso funciona bem com o meu exemplo. Como eu tenho que escrever um título de capítulo que contém um espaço como Ergebnisse und Diskussion? Eu tentei com if ($3=="Ergebnisse und Diskussion"), mas isso não parece encontrar a linha correta
MostlyHarmless
@Martin: Espaços são tratados como separadores. if ($3=="Ergebnisse" && $4=="und" && $5=="Diskussion") Deveria trabalhar. Mas o número da página não será mais armazenado $4. Eu atualizarei minha resposta.
Dennis
obrigado por sua ajuda - desculpe, eu deveria ter solicitado diretamente a string mais complicada, mas eu não pensei sobre esta possível complicação
MostlyHarmless
1
@Dennis: e agora sua resposta parece com a minha :)
akira
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 via:

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

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

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

se você precisar mais apertado 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`
akira
fonte
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"
grawity
fonte
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), devido à cut.

Daniel Beck
fonte
1
não vai mesmo trabalhar com números diferentes, digamos 1 ou 100
akira
@akira Se existem muitas páginas entre introdução e manchetes de capítulos sobre fundamentos, ele está fazendo algo errado :-) Mas você está certo, é claro.
Daniel Beck
@DanielBeck: Obrigado pelo seu anwer! Como você já declarou (e @akira diz), o uso dessa solução é bastante limitado porque os números precisam estar exatamente na mesma posição a cada vez. As soluções com awk são mais flexíveis.
MostlyHarmless
@ Martin Enquanto você está certo, você nunca sequer sugeriu que, por exemplo você deseja aplicar uma solução a outros nomes de capítulo. Muito pelo contrário com o seu primeiro item da lista ...
Daniel Beck
@DanielBeck: isso é verdade - minha pergunta estava incompleta.
MostlyHarmless