Beberapa sistem memiliki truncateperintah yang memotong file ke sejumlah byte (bukan karakter).
Saya tidak tahu ada yang memotong ke sejumlah karakter, meskipun Anda dapat menggunakan perlyang diinstal secara default pada kebanyakan sistem:
perl
perl -Mopen=locale -ne '
BEGIN{$/ = \1234} truncate STDIN, tell STDIN; last' <> "$file"
Dengan -Mopen=locale, kami menggunakan gagasan lokal tentang karakter apa (jadi di lokal menggunakan charset UTF-8, itu karakter yang dikodekan UTF-8). Ganti dengan -CSjika Anda ingin I / O didekodekan / disandikan dalam UTF-8 terlepas dari charset lokal.
$/ = \1234: kami mengatur pemisah rekaman ke referensi ke integer yang merupakan cara untuk menentukan rekaman dengan panjang tetap (dalam jumlah karakter ).
kemudian setelah membaca catatan pertama, kita memotong stdin di tempat (jadi di akhir catatan pertama) dan keluar.
GNU sed
Dengan GNU sed, Anda bisa melakukannya (dengan asumsi file tidak mengandung karakter NUL atau urutan byte yang tidak membentuk karakter yang valid - keduanya harus benar dari file teks):
sed -Ez -i -- 's/^(.{1234}).*/\1/' "$file"
Tapi itu jauh kurang efisien, karena membaca file secara penuh dan menyimpannya dalam memori, dan menulis salinan baru.
GNU awk
Sama dengan GNU awk:
awk -i inplace -v RS='^$' -e '{printf "%s", substr($0, 1, 1234)}' -E /dev/null "$file"
-e code -E /dev/null "$file" menjadi salah satu cara untuk memberikan nama file yang sewenang-wenang kepada gawk
RS='^$': mode slurp .
Shell bawaan
Dengan ksh93, bashatau zsh(dengan cangkang selain zsh, dengan asumsi konten tidak mengandung byte NUL):
content=$(cat < "$file" && echo .) &&
content=${content%.} &&
printf %s "${content:0:1234}" > "$file"
Dengan zsh:
read -k1234 -u0 s < $file &&
printf %s $s > $file
Atau:
zmodload zsh/mapfile
mapfile[$file]=${mapfile[$file][1,1234]}
Dengan ksh93atau bash(waspadalah itu palsu untuk karakter multi-byte dalam beberapa versibash ):
IFS= read -rN1234 s < "$file" &&
printf %s "$s" > "$file"
ksh93juga dapat memotong file di tempat alih-alih menulis ulang dengan <>;operator pengalihan:
IFS= read -rN1234 0<>; "$file"
iconv + head
Untuk mencetak 1234 karakter pertama, opsi lain adalah mengonversi ke pengkodean dengan jumlah byte tetap per karakter seperti UTF32BE/ UCS-4:
iconv -t UCS-4 < "$file" | head -c "$((1234 * 4))" | iconv -f UCS-4
head -ctidak standar, tetapi cukup umum. Setara standar akan dd bs=1 count="$((1234 * 4))"tetapi akan kurang efisien, karena akan membaca input dan menulis output satu byte pada suatu waktu¹. iconvadalah perintah standar tetapi nama penyandian tidak terstandarisasi, sehingga Anda mungkin menemukan sistem tanpaUCS-4
Catatan
Bagaimanapun, meskipun output akan memiliki paling banyak 1.234 karakter, itu mungkin berakhir menjadi teks yang tidak valid, karena mungkin akan berakhir pada baris yang tidak dibatasi.
Perhatikan juga bahwa walaupun solusi tersebut tidak memotong teks di tengah karakter, mereka dapat memecahnya di tengah grapheme , seperti yang édinyatakan sebagai U + 0065 U + 0301 ( ediikuti oleh kombinasi aksen akut), atau grapheme suku kata Hangul dalam bentuk terurai.
¹ dan pada input pipa Anda tidak dapat menggunakan bsnilai selain 1 secara andal kecuali Anda menggunakan iflag=fullblockekstensi GNU, seperti ddhalnya bacaan singkat jika membaca pipa lebih cepat daripada iconvmengisinya
cutmasih tidak mendukung karakter multi-byte. Jika ya, Anda bisa melakukannyacut -zc-1234 | tr -d '\0'.