Oggi vedremo come manipolare un testo, e in particolare un file di sottotitoli… utilizzerò questo punto di partenza per introdurvi a due potentissimi strumenti tipici del mondo GNU/Linux (e Unix più in generale).

L’idea iniziale era di scrivere un unico articolo che trattasse regex, sed e awk tutti assieme! L’articolo stava però diventando mastodontico! Quindi qui dentro vi linkero gli articoli che introducono regexp, sed e awk!

Al momento in cui scrivo l’articolo sulle regular expression e su sed sono finiti e saranno quindi già linkati! Sto ancora lavorando sull’articolo di awk (più lungo e complesso) che arriverà presto, impegni permettendo…

Qui vi proporrò un esempio pratico che funge da “antipasto” per le prossime guide: un file dei sottotitoli “srt” non conforme allo standard “srt”, e quindi con dei difetti da sistemare…

Questi difetti sono 2(+1):

  1. ad ogni riga del file ne segue una vuota che vogliamo eliminare (il che significa voler eliminare tutte le righe pari del file)
  2. il formato tempo non è corretto, manca una virgola tra i secondi e i millesimi di secondo! Vogliamo aggiungerla automaticamente
  3. risincroniziamo il file dei sottotitoli con il video: questo non è un problema di conformità allo standard srt ne un problema che ho risolto con sed o awk; l’ho aggiungo per completezza al fine di mostrare come risincronizzare un file di sottotitoli desincronizzato con l’audio…

Partiamo da un testo fatto così:

Testo di partenza

e ne vogliamo uno così:

Risultato

Ovviamente ha poco senso per file così corti: immaginate di avere un file con migliaia di righe da sistemare! A mano diventa improponibile… ecco dove entrano in scena awk e sed.

Per il punto uno useremo “awk”, per il punto due “sed” e per il punto 3 “gaupol” (uno dei software per manipolare i sottotitoli che potete trovare in Linux) anche se non ci siano particolari vincoli (avremmo potuto fare tutto sia con sed che con awk)

Supponiamo che il file iniziale si chiami “sottotitoli.srt”: aprite un terminale nella cartella dove c’è il vostro file

Nota: mi scuso per aver utilizzato delle immagini ma con wordpress non riuscivo a mantenere le corrette spaziature e righe vuote!! (venivano automaticamente eliminate) se volete provare potete trovare il primo file (copia-incollabile) qui, e il risultato qui.

Rimuovere tutte le righe pari:

cat sottotitoli.srt | awk 'NR%2==1' > sottotitoli-dispari.srt

Spiegazione:

Così avrete creato il file “sottotitoli-dispari.srt” che, come potete verificare, manterrà le sole righe dispari, o se preferite sarà privo di tutte le righe pari.

Il comando “cat” non fa altro che leggere e stampare il file (provate)

con il simbolo ‘|’ mandiamo il file al comando dopo, in questo caso awk

la stringa tra apici ‘NR%2==1‘ significa “(se) resto di (numero-di-riga / 2) è uguale a 1″: come sapete se il resto della divisione per 2 è 1 allora il numero che è stato diviso è dispari.

per ‘awk’ questo significa: quando la condizione è verificata allora stampa il risultato, altrimenti scartalo: quindi scarteremo tutte le righe pari e manterremo le dispari! Se aveste messo uno zero invece dell’uno potevate stampare le sole righe pari e con lo stesso metodo si può scartare una riga ogni 4 o ogni 7 a piacimento.

Infine con ‘> sottotitoli-dispari.srt‘ diciamo semplicemente di mettere il risultato in un nuovo file chiamato ‘sottotitoli-dispari.srt’ anziché stamparlo a video.

Inseriamo la virgola dove necessario

sed -e 's/[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}/&,/g' sottotitoli-dispari.srt > sottotitoli-convirgola.srt

Spiegazione:

il comando sed elabora dei testi: quel che facciamo qui è eseguire uno script (opzione -e) che definiamo tra gli apici.

Nel nostro caso lo script applica una sostituzione sfruttando le espressioni regolari, per comprendere facciamo qualche esempio…

Questo istruzione qui sotto sostituisce tutte le occorrenze di “itaglia” con “Italia”, o comunque nel file di ingresso

s/itaglia/Italia/g

Senza la “g” finale avrebbe sostituito solamente la prima occorrenza di “itaglia” per ogni riga. Niente che non potete fare con qualunque editor, per ora🙂

Invece questo sostituisce ogni occorrenza di “Linux” o “linux” con “GNU/Linux” o “GNU/linux” a seconda di come sia il primo🙂

sed -e 's/[Ll]inux/GNU\/&/g' esempio.txt

Qui sono state introdotte un po’ ci cose:

prima di tutto la barra “/” di GNU/Linux è un carattere speciale quindi perché venga proprio considerato come “/” e stampato dobbiamo anteporgli quest’altra barra “\”: “\/” verrà stampato come “/”. Visto che il comando si aspetta quacosa con 3 slash tipo ‘s/testo/altro testo/’ se noi inseriamo un altro slash (/) lì dentro non saprebbe più che fare: se però inseriamo ‘\/’ sà esattamente che quella va considerata come testo

Stavolta la stringa ricercata è un po’ strana: “[Ll]inux”. Questo significa semplicemente: cerca le parole “Linux” e “linux”, le parentesi quadre dicono che il primo carattere può essere sia L maiuscolo che l minuscolo. Questa è un’espressione regolare di base, anche chiamata regex, verranno introdotte meglio qui sotto.

L’ultima stranezza di questo esempio è la stringa (testo) di sostituzione che presenta una e-commerciale (&): essa significa: metti al posto della & il testo trovato, così se il testo trovatè è “Linux” verrà mantenuto “Linux” così come se il testo trovato è “linux” resterà “linux”.

eccone un esempio…

prima:

questo è un esempio di cosa si può fare con i tool di Linux il famoso software free! Avete visto la potenza del terminale in linux? E questo è niente!!

dopo:

questo è un esempio di cosa si può fare con i tool di GNU/Linux il famoso software free! Avete visto la potenza del terminale in GNU/linux? E questo è niente!!

Avrete intuito che “s/[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}/&,/g” va in qualche modo a cercare le stringhe fatte così: “12:34:56” e vi aggiunge una virgola alla fine.

Per comprendere com’è costruita quella stringa e per permettervi di scrivere voi stessi un espressione di regex vi serve una piccola introduzione alle espressioni regolari

Qualche nota in più su awk e sed

Se avete un testo da monipolare questi due comandi sono i più potenti strumenti a vostra disposizione! In particolare abbinati al linguaggio della shell di Unix/Linux (sh, bash, altro) vi permettono di fare davvero di tutto!

Qui vi introdurrò al loro utilizzo, io stesso non sono un guru ne dell’uno ne dell’altro! Quando ho bisogno di qualcosa leggo il manuale (man sed, man awk), cerco su internet e, solo successivamente, chiedo in qualche chat. Una volta introdotti dovreste essere in grado di proseguire da soli lo studio se sarete interessati o avrete bisogno, non chiedetemi supporto perché non sarei probabilmente in grado di rispondervi🙂 [mi riservo di modificare questa frase in futuro se dovessi diventare un guru di awk/sed]. E comunque leggetevi gli articoli linkati qui e sarete il vostro supporto! Questi articoli verranno mantenuti aggiornati mano a mano che imparo nuove cose su questi strumenti…

Leggendo il contenuto di questi Link vi sarà facilitato cominciare ad utilizzare questi strumenti…

Operazioni sui sottotitoli srt

Per completezza, visto che l’esempio tratta un file dei sottotitoli…

Forse vi sarete chiesti perché talvolta i sottotitoli si sfalsano rispetto all’audio e le immagini sempre più proseguendo nella visione di un video!

In generale il problema è che i sottotitoli sono stati creati per un video con un certo “frame rate per second” (fps) mentre il video che voi avete davanti ne ha un altro… Questo può accadere se ad esempio ricodificate il video!

L’altra cosa che può accadere è uno sfalsamento (offset) di qualche secondo o minuto, anche qui può dipendere da diversi fattori ma in sostanza significa che il vostro video comincia prima o dopo rispetto ai sottotitoli…

In genere gli fps di un video sono 3: 23.976 fps, 25 fps, 29.97 fps.

sul mio esempio ho ipotizzato che quei sottotitoli fossero stati sincronizzati a 23.976 fps e che il video fosse a 25 fps. Ho aperto con gaupol il file e dal menù strumenti ho convertito gli fps dei sottotitoli usando “convert framerate” selezionando come fps di partenza 23.976 e di arrivo 25🙂

Se i sottotitoli “vanno troppo in fretta” rispetto al video significa che dovete aumentare gli fps dei sottotitoli, se “vanno sempre più lenti” dovete ridurli. Gli fps di arrivo devono sempre essere quelli del vostro video, cosa che potete scoprire con il vostro software per visualizzare i video (io uso mplayer da linea di comando e me lo dice :P)

Poi ho ipotizzato che i sottotitoli anticipassero di 1 secondo il momento esatto in cui mi aspettavo comparissero, per correggerlo sempre in gaupol da menù strumenti con “shift position” ho impostato 1 secondo di offset per shiftarli tutti in avanti di un secondo!

Se avete un sottotitolo di cui non conoscete questi dati lavorate su delle copie e fate delle prove per gli fps. Quando lo sfalsamento dei sottotitoli resta costante (quindi non aumenta/diminuisce con l’avanzare del video o film) potete misurare a occhio l’offset e sistemarlo…

La cosa più difficile è capire se dovete prima sistemare l’offset e poi shiftare o meno…. in genere prima vanno sistemati gli fps e poi l’offset comunque!