programmazione,

Script per tutti i giorni: semplici modifiche alle stringhe di testo

Sabino Maggi Sabino Maggi Segui 23-Nov-2018 · 8 minuti di lettura
Condividi

– Foto: telwink su Flickr.

Succede più spesso di quanto mi renda conto. Devo rinominare dei file, modificare un testo o fare altri pasticci con i miei documenti. Potrei usare una delle tante applicazioni ad hoc fatte per fare proprio quello. Ma perché perdere tempo ad installare ed imparare ad usare l’ennesima applicazione se con il Terminale posso fare prima (e meglio)?

Basta qualche comando ben piazzato nel Terminale, a volte qualche piccolo script in bash o in python, e si possono fare cose bellissime con poco sforzo.

E una volta fatte, perché tenerli per se e non condividerli, magari proprio qui? L’impulso iniziale me l’ha dato Federico “frix” Morchio durante una discussione sul canale Goedel di Slack gestito dal sempre ottimo Lucio Bragagnolo (aka… oops, noto anche come Lux, Loox e tanti altri alias).

Attenzione! Questo e i futuri post sull’argomento non saranno delle introduzioni a bash, a python, al Terminale di macOS (tendo sempre a dimenticare che non si chiama più OS X!), per quelle ci sono un sacco di ottime guide in rete. Chi vuole fare in fretta può iniziare leggendo la mia piccola guida a bash di qualche anno fa, Script di shell in OS X e magari anche Compleanno con permessi, la ripresa di un vecchio post sull’ormai defunto Ping che di fatto mi ha fatto iniziare l’esperienza di blogger.

Cominciamo con un antipasto veloce, una cosa apparentemente inutile (o quasi), ma che serve a dare una idea delle potenzialità di bash e di come, partendo da un’idea semplice, si possa trasformarla a poco a poco in qualcosa di più pratico e adatto ad un uso quotidiano.

Manipolare i nomi dei file

La prima cosa che faccio quando inizio a scrivere un nuovo post è creare un file Markdown con i metadati (titolo, data di pubblicazione, categoria e tag, chi usa Jekyll o Octopress sa di cosa parlo), a cui assegno un nome temporaneo. Una volta deciso il titolo definitivo, rinomino il file in un modo più razionale, in modo che possa ritrovarlo facilmente.

Per farlo seguo la convenzione sui nomi dei file di Jekyll,1 secondo la quale il nome del file deve essere scritto come YYYY-MM-DD-titolo-del-post.md, dove YYYY indica l’anno, MM il mese e DD il giorno di pubblicazione (espressi rispettivamente con quattro e due cifre) e parole e numeri vanno separati con un trattino invece che con uno spazio. Sembra una cosa inutilmente complicata, ma permette di tenere ordinati i file in base alla data anche quando se ne modifica il contenuto in un secondo tempo. E comunque, evitare di utilizzare gli spazi nei nomi dei file è ancora oggi la cosa più razionale da fare nei sistemi basati su Unix come macOS.

Per la data non ci sono problemi, nei metadati è già scritta nel formato giusto, per cui è sufficiente copiarla ed incollarla direttamente nel nome del file tramite il Finder. Ma il titolo? Potrei usare il Finder anche per il titolo, inserendolo dopo la data nel nome del file e sostituendo a mano gli spazi con i trattini. Però è facile sbagliare, soprattutto quando il titolo è lungo. Ancora più facile è non essere consistenti, usando ogni volta una forma leggermente diversa e mandando a pallino i vantaggi dati dall’utilizzare nomi di file ben definiti.

E poi, vuoi mettere il divertimento di farlo fare a bash?

Un pezzo alla volta

Prendiamo come esempio il titolo di un post di qualche mese fa, “La privacy al tempo dell’Internet of Things: gran finale”. Per trasformare il titolo originale in una sequenza di parole separate da trattini è sufficiente lanciare il Terminale ed eseguire il comando

$ echo "La privacy al tempo dell'Internet of Things: gran finale" | sed "s/ /-/g"

dove echo scrive la stringa nel Terminale e la invia tramite il | (pipe) a sed, che si occupa di cercare tutti gli spazi e di sostituirli con un trattino, ottenendo

La-privacy-al-tempo-dell'Internet-of-Things:-gran-finale

Non male, ma ci sono due o tre cosette da sistemare.

Problema numero 1 (banale). Il formato di Jekyll prevede implicitamente che il nome del file sia scritto tutto in minuscolo. Personalmente trovo che questa forma sia più gradevole, ma è anche utile a semplificare e a rendere univoco l’ordinamento dei file (una fissazione, lo so, ma quando si maneggiano tantissimi file ogni giorno diventa una cosa fondamentale per lavorare meglio). Si può fare così

$ echo "La privacy al tempo dell'Internet of Things: gran finale" | tr "[:upper:]" "[:lower:]"

dove tr trasforma i caratteri maiuscoli ([:upper:]) in minuscoli ([:lower:]), ottenendo

la privacy al tempo dell'internet of things: gran finale

Domanda #1: cosa succede se nel comando precedente si usa tr "[:lower:]" "[:upper:]"?

Problema numero 2 (importante). Nei nomi dei file è preferibile usare solo lettere non accentate, numeri e alcuni caratteri di separazione: trattino, underscore e (se proprio dobbiamo) spazio. Se possibile è meglio evitare di usare il punto, che normalmente serve per separare il nome del file vero e proprio dall’estensione (caratteristica che è stata usata parecchio per distribuire file contenti virus ma che apparivano legittimi). Tutto gli altri caratteri devono essere rigorosamente evitati, perché spesso hanno significati speciali per il sistema operativo e creano solo guai.

Per togliere la punteggiatura possiamo usare la stessa tecnica di sopra,

$ echo "La privacy al tempo dell'Internet of Things: gran finale" | sed "s/[[:punct:]]//g"

dove in questo caso sed cerca tutti i caratteri di punteggiatura ([[:punct:]]) e li sostituisce con… niente (cioè li toglie), ottenendo in uscita

La privacy al tempo dellInternet of Things gran finale

Problema numero 3 (specifico). Il comando di prima rimuove anche gli apostrofi (che è sempre bene evitare di mettere nei nomi dei file, perché potrebbero dare problemi su sistemi operativi meno liberali di macOS).2 Piuttosto che buttarli via, è preferibile però sostituirli con un trattino, usando ancora una volta sed

$ echo "La privacy al tempo dell'Internet of Things: gran finale" | sed "s/'/-/g"

che da in uscita

La privacy al tempo dell-Internet of Things: gran finale

Mettiamo tutto insieme

Usare bash (o qualunque altra shell di Unix) è un po’ come usare il Lego dove, mettendo insieme dei piccoli mattoncini di forme e colori diversi, si può costruire una portaerei (o quasi). Con bash si prendono dei semplici comandi come quelli visti prima, si mettono nell’ordine giusto, si collega l’output di un comando con l’input di quello successivo tramite il | (pipe), e alla fine si riescono a fare delle cose anche piuttosto sofisticate.

In questo caso, il comando

$ echo "La privacy al tempo dell'Internet of Things: gran finale" | tr "[:upper:]" "[:lower:]" | sed "s/'/ /g" | sed "s/[[:punct:]]//g" | sed "s/ /-/g"

genera la stringa

la-privacy-al-tempo-dell-internet-of-things-gran-finale

pronta per essere utilizzata come nome del file.

Domanda #2: Cosa succede se cambio l’ordine dei comandi? Perché questo è l’ordine migliore per convertire un titolo nel formato desiderato?

Domanda #3: Perché nel primo sed questa volta ho sostituito l’apostrofo ' con uno spazio (mentre nella descrizione del problema numero 3 avevo usato un trattino)?

Chi ha avuto la pazienza di leggere fin qui, si starà chiedendo che senso abbia complicarsi la vita con il Terminale e con bash, quando è molto più veloce modificare il titolo a mano nel Finder.

Tutto vero, ma è altrettanto vero che il post è stato più che altro una scusa per introdurre due comandi come sed e tr, molto utili ma anche molto poco conosciuti. E poi, partendo da questa base si possono costruire delle cose molto più utili, ma questo lo vedremo la prossima volta.

Revisioni

3-12-2018: Corretta una incongruenza nel testo originale, nel quale veniva usato una volta sed e un’altra tr per rimuovere i caratteri di punteggiatura.

  1. Che poi è praticamente la stessa convenzione che usa Wordpress per generare i nomi dei post. 

  2. La gestione generale dei caratteri accentati nei nomi dei file è un problema molto più complesso, che è meglio rimandare ad un post specifico sull’argomento, ammesso che ci sia interesse per l’argomento. 

Sabino Maggi
Pubblicato da Sabino Maggi Segui
Commenti

Aggiungi un commento