Alcuni sistemi hanno un truncate
comando che tronca i file su un numero di byte (non caratteri).
Non conosco nessuno che si tronchi in un numero di caratteri, anche se potresti ricorrere a perl
quale è installato di default sulla maggior parte dei sistemi:
perl
perl -Mopen=locale -ne '
BEGIN{$/ = \1234} truncate STDIN, tell STDIN; last' <> "$file"
Con -Mopen=locale
, usiamo la nozione di locale di cosa sono i caratteri (quindi nelle versioni locali che usano il set di caratteri UTF-8, ovvero caratteri codificati UTF-8). Sostituire con -CS
se si desidera che gli I / O vengano decodificati / codificati in UTF-8 indipendentemente dal set di caratteri della locale.
$/ = \1234
: impostiamo il separatore di record su un riferimento a un numero intero che è un modo per specificare record di lunghezza fissa (in numero di caratteri ).
quindi, dopo aver letto il primo record, tronciamo stdin in posizione (quindi alla fine del primo record) e usciamo.
GNU sed
Con GNU sed
, potresti farlo (supponendo che il file non contenga caratteri NUL o sequenze di byte che non formano caratteri validi - entrambi dovrebbero essere veri per i file di testo):
sed -Ez -i -- 's/^(.{1234}).*/\1/' "$file"
Ma è molto meno efficiente, in quanto legge il file per intero, lo memorizza per intero in memoria e ne scrive una nuova copia.
GNU awk
Lo stesso con GNU awk
:
awk -i inplace -v RS='^$' -e '{printf "%s", substr($0, 1, 1234)}' -E /dev/null "$file"
-e code -E /dev/null "$file"
essendo un modo per passare nomi di file arbitrari a gawk
RS='^$'
: modalità slurp .
Shell incorporati
Con ksh93
, bash
o zsh
(con shell diverse da zsh
, supponendo che il contenuto non contenga byte NUL):
content=$(cat < "$file" && echo .) &&
content=${content%.} &&
printf %s "${content:0:1234}" > "$file"
Con zsh
:
read -k1234 -u0 s < $file &&
printf %s $s > $file
O:
zmodload zsh/mapfile
mapfile[$file]=${mapfile[$file][1,1234]}
Con ksh93
o bash
(attenzione è falso per i caratteri multi-byte in diverse versioni dibash
):
IFS= read -rN1234 s < "$file" &&
printf %s "$s" > "$file"
ksh93
può anche troncare il file in atto invece di riscriverlo con il suo <>;
operatore di reindirizzamento:
IFS= read -rN1234 0<>; "$file"
iconv + head
Per stampare i primi 1234 caratteri, un'altra opzione potrebbe essere quella di convertire in una codifica con un numero fisso di byte per carattere come UTF32BE
/ UCS-4
:
iconv -t UCS-4 < "$file" | head -c "$((1234 * 4))" | iconv -f UCS-4
head -c
non è standard, ma abbastanza comune. Un equivalente standard sarebbe dd bs=1 count="$((1234 * 4))"
ma sarebbe meno efficiente, in quanto leggerebbe l'ingresso e scriverà l'uscita un byte alla volta¹. iconv
è un comando standard ma i nomi di codifica non sono standardizzati, pertanto è possibile trovare sistemi senzaUCS-4
Appunti
In ogni caso, sebbene l'output abbia un massimo di 1234 caratteri, potrebbe non essere un testo valido, in quanto potrebbe finire in una riga non delimitata.
Nota anche che mentre quelle soluzioni non tagliano il testo nel mezzo di un personaggio, potrebbero romperlo nel mezzo di un grafema , come un é
espresso come U + 0065 U + 0301 ( e
seguito da un accento acuto combinato), o grafemi di sillabe Hangul nelle loro forme decomposte.
¹ e sull'input della pipe non è possibile utilizzare bs
valori diversi da 1 in modo affidabile a meno che non si utilizzi l' iflag=fullblock
estensione GNU, poiché si dd
potrebbero fare letture brevi se legge la pipe più velocemente di quanto la iconv
riempia
cut
still non supporta i caratteri multi-byte. Se così fosse, potresti farlocut -zc-1234 | tr -d '\0'
.