Một số hệ thống có truncate
lệnh cắt các tệp thành một số byte (không phải ký tự).
Tôi không biết bất kỳ đoạn nào cắt ngắn một số ký tự, mặc dù bạn có thể sử perl
dụng mặc định được cài đặt trên hầu hết các hệ thống:
perl
perl -Mopen=locale -ne '
BEGIN{$/ = \1234} truncate STDIN, tell STDIN; last' <> "$file"
Với -Mopen=locale
, chúng tôi sử dụng khái niệm của địa phương về các ký tự là gì (vì vậy trong các địa phương sử dụng bộ ký tự UTF-8, đó là các ký tự được mã hóa UTF-8). Thay thế bằng -CS
nếu bạn muốn I / O được giải mã / mã hóa trong UTF-8 bất kể bộ ký tự của miền địa phương.
$/ = \1234
: chúng tôi đặt dấu tách bản ghi thành tham chiếu đến một số nguyên là cách chỉ định các bản ghi có độ dài cố định (theo số lượng ký tự ).
sau đó khi đọc bản ghi đầu tiên, chúng tôi cắt ngắn stdin tại chỗ (vì vậy ở phần cuối của bản ghi đầu tiên) và thoát.
GNU sed
Với GNU sed
, bạn có thể làm (giả sử tệp không chứa các ký tự NUL hoặc chuỗi byte không tạo thành các ký tự hợp lệ - cả hai đều đúng với tệp văn bản):
sed -Ez -i -- 's/^(.{1234}).*/\1/' "$file"
Nhưng điều đó kém hiệu quả hơn nhiều, vì nó đọc toàn bộ tệp và lưu trữ toàn bộ trong bộ nhớ và viết một bản sao mới.
GNU awk
Tương tự với GNU awk
:
awk -i inplace -v RS='^$' -e '{printf "%s", substr($0, 1, 1234)}' -E /dev/null "$file"
-e code -E /dev/null "$file"
là một cách để chuyển tên tệp tùy ý đến gawk
RS='^$'
: chế độ bùn .
Vỏ tích hợp
Với ksh93
, bash
hoặc zsh
(với các shell khác zsh
, giả sử nội dung không chứa NUL byte):
content=$(cat < "$file" && echo .) &&
content=${content%.} &&
printf %s "${content:0:1234}" > "$file"
Với zsh
:
read -k1234 -u0 s < $file &&
printf %s $s > $file
Hoặc là:
zmodload zsh/mapfile
mapfile[$file]=${mapfile[$file][1,1234]}
Với ksh93
hoặc bash
(hãy cẩn thận, nó không có thật cho các ký tự nhiều byte trong một số phiên bảnbash
):
IFS= read -rN1234 s < "$file" &&
printf %s "$s" > "$file"
ksh93
cũng có thể cắt tệp tại chỗ thay vì viết lại bằng <>;
toán tử chuyển hướng của nó :
IFS= read -rN1234 0<>; "$file"
iconv + đầu
Để in 1234 ký tự đầu tiên, một tùy chọn khác có thể là chuyển đổi thành mã hóa với số byte cố định trên mỗi ký tự như UTF32BE
/ UCS-4
:
iconv -t UCS-4 < "$file" | head -c "$((1234 * 4))" | iconv -f UCS-4
head -c
không chuẩn, nhưng khá phổ biến. Một tương đương tiêu chuẩn sẽ có dd bs=1 count="$((1234 * 4))"
nhưng sẽ kém hiệu quả hơn, vì nó sẽ đọc đầu vào và ghi đầu ra một byte mỗi lần¹. iconv
là một lệnh tiêu chuẩn nhưng tên mã hóa không được tiêu chuẩn hóa, vì vậy bạn có thể tìm thấy các hệ thống mà không cóUCS-4
Ghi chú
Trong mọi trường hợp, mặc dù đầu ra sẽ có tối đa 1234 ký tự, nhưng cuối cùng nó có thể không phải là văn bản hợp lệ, vì nó có thể kết thúc bằng một dòng không phân cách.
Cũng lưu ý rằng mặc dù các giải pháp đó sẽ không cắt văn bản ở giữa một ký tự, nhưng chúng có thể phá vỡ nó ở giữa biểu đồ , giống như được é
thể hiện dưới dạng U + 0065 U + 0301 ( e
tiếp theo là dấu trọng âm kết hợp), hoặc đồ thị âm tiết Hangul trong các hình thức phân tách của chúng.
Và trên đầu vào đường ống, bạn không thể sử dụng bs
các giá trị ngoài 1 một cách đáng tin cậy trừ khi bạn sử dụng iflag=fullblock
phần mở rộng GNU, cũng như dd
có thể đọc ngắn nếu nó đọc ống nhanh hơn iconv
lấp đầy nó
cut
vẫn không hỗ trợ các ký tự nhiều byte. Nếu nó đã làm, bạn có thể làmcut -zc-1234 | tr -d '\0'
.