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.