Come estrarre due numeri da due stringhe e calcolare la differenza in Bash?


1

Ho un file di testo che contiene (tra gli altri) le seguenti righe:

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

Come posso

  • prendi le 2 linee da questo file di testo (che conterranno sempre }Einleitung resp. }Grundlagen} e
  • estrai i 2 numeri di pagina (in questo caso 27 e 35),
  • calcola la differenza 35-27 = 8 e
  • salva la differenza ( 8 ) dei due numeri in una variabile

Forse con uno script bash in Mac OS X?


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

Risposte:


3

Non so se Mac OS X ha awk. Se lo fa, dovrebbe funzionare:

Questo dovrebbe funzionare:

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

Come funziona:

  • FS="[{}]+" imposta il separatore di campo su qualsiasi combinazione di parentesi graffe.
  • $4 si riferisce al terzo file sulla linea (separato da parentesi graffe).
  • DIFFERENZ=$(...) valuta il comando ... e memorizza l'output in DIFFERENZ.


grazie, funziona bene con il mio esempio Come devo scrivere un titolo di capitolo che contenga uno spazio simile Ergebnisse und Diskussion? Ci ho provato if ($3=="Ergebnisse und Diskussion"), ma quello non sembra trovare la linea corretta
— MostlyHarmless

@ Martin: gli spazi sono trattati come separatori. if ($3=="Ergebnisse" && $4=="und" && $5=="Diskussion") dovrebbe funzionare. Ma il numero di pagina non verrà più memorizzato $4. Aggiornerò la mia risposta
— Dennis

grazie per il tuo aiuto - scusa, avrei dovuto chiedere direttamente la stringa più complicata, ma non ho pensato a questa possibile complicazione
— MostlyHarmless

1
@Dennis: e ora la tua risposta assomiglia al mio :)
— 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
}

puoi chiamarlo tramite:

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

stamperà 8. è possibile memorizzare quel numero in una variabile bash come questa:

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

se ne hai bisogno più stretto potresti anche riscriverlo calc.awk non essere un file separato ma una sola riga:

$> nr=`awk 'BEGIN{FS="}{";g=0;e=0}/Einleitung/{e=$3;}/Grundlagen/{g=$3;}END{print g-e;}' < in.txt`

1

Pure bash 4.x e mostra le differenze per ogni capitolo:

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"

0
$ DIFFERENCE=$(( $( cat FILENAME | grep Grundlagen | head -n1 | cut -c26-27 ) - $( cat FILENAME | grep Einleitung  | head -n1 | cut -c26-27 ) ))
$ echo $DIFFERENCE
8

Ciò richiede che le linee abbiano sempre esattamente questo aspetto (cioè nessun titolo diverso), a causa del cut.


1
non funzionerà nemmeno con numeri diversi, diciamo 1 o 100
— akira

@akira Se ci sono così tante pagine tra titoli introduttivi e titoli fondamentali, sta facendo qualcosa di sbagliato :-) Ma hai ragione, ovviamente.
— Daniel Beck

@ DanielBeck: grazie per il tuo anwer! Come già dichiari (e dice @akira), l'uso di questa soluzione è abbastanza limitato perché i numeri devono essere esattamente nella stessa posizione ogni volta. Le soluzioni con awk sono più flessibili.
— MostlyHarmless

@ Martin Mentre hai ragione, non hai nemmeno accennato che, ad es. vuoi applicare una soluzione ad altri nomi di capitoli. Al contrario con il tuo primo elemento della lista ...
— Daniel Beck

@ DanielBeck: questo è vero - la mia domanda era incompleta.
— MostlyHarmless
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.