Semplificando: coda
Non dovremmo aver bisogno di un'espressione regolare, o più di un processo, solo per contare i caratteri.
Il comando tail
, spesso usato per mostrare le ultime righe di un file, ha un'opzione -c
( --bytes
), che sembra essere lo strumento giusto per questo:
$ printf 123456789 | tail -c 3
789
(Quando sei in una shell, ha senso usare un metodo come nella risposta di mikeserv, perché salva l'avvio del processo per tail
.)
Veri personaggi Unicode?
Ora chiedi gli ultimi tre personaggi ; Non è questo che ti dà questa risposta: genera gli ultimi tre byte !
Finché ogni carattere è un byte, tail -c
funziona e basta. Così può essere utilizzato se il set di caratteri è ASCII
, ISO 8859-1
o una sua variante.
Se si dispone di input Unicode, come nel UTF-8
formato comune , il risultato è errato:
$ printf 123αβγ | tail -c 3
�γ
In questo esempio, usando UTF-8
, i caratteri greci alpha, beta e gamma sono lunghi due byte:
$ printf 123αβγ | wc -c
9
L'opzione -m
può almeno contare i caratteri unicode reali:
printf 123αβγ | wc -m
6
Ok, quindi gli ultimi 6 byte ci daranno gli ultimi 3 caratteri:
$ printf 123αβγ | tail -c 6
αβγ
Quindi, tail
non supporta la gestione di caratteri generali e non ci prova nemmeno (vedi sotto): gestisce linee di dimensioni variabili, ma non caratteri di dimensioni variabili.
Mettiamola così: tail
è giusto per la struttura del problema da risolvere, ma sbagliata per il tipo di dati.
Coreutils GNU
Guardando oltre, si scopre che ti coreutils GNU, la collezione di strumenti di base come sed
, ls
, tail
e cut
, non è ancora pienamente internazionalizzato. Il che riguarda principalmente il supporto di Unicode.
Ad esempio, cut
sarebbe un buon candidato da utilizzare al posto della coda qui per il supporto del personaggio; Ha opzioni per lavorare su byte o caratteri, -c
( --bytes
) e -m
( --chars
);
Solo che -m
/ non --chars
è, a partire dalla versione
cut (GNU coreutils) 8.21
2013,
non implementato!
Da info cut
:
`-c CHARACTER-LIST'
`--characters=CHARACTER-LIST'
Select for printing only the characters in positions listed in CHARACTER-LIST.
The same as `-b' for now, but internationalization will change that.
Vedi anche questa risposta a Non puoi usare `cut -c` (` --characters`) con UTF-8? .
grep -o '.\{3\}$'