Einige Systeme verfügen über einen truncate
Befehl, mit dem Dateien auf eine bestimmte Anzahl von Bytes (keine Zeichen) gekürzt werden .
Ich kenne keine, die auf eine Reihe von Zeichen gekürzt sind, obwohl Sie auf die zurückgreifen könnten, perl
die auf den meisten Systemen standardmäßig installiert ist:
perl
perl -Mopen=locale -ne '
BEGIN{$/ = \1234} truncate STDIN, tell STDIN; last' <> "$file"
Mit verwenden -Mopen=locale
wir die Vorstellung des Gebietsschemas, was Zeichen sind (in Gebietsschemas, die den UTF-8-Zeichensatz verwenden, sind das UTF-8-codierte Zeichen). Ersetzen Sie durch, -CS
wenn I / O unabhängig vom Zeichensatz des Gebietsschemas in UTF-8 decodiert / codiert werden soll.
$/ = \1234
: Wir setzen das Datensatztrennzeichen auf einen Verweis auf eine Ganzzahl, mit der Datensätze mit fester Länge (in Zeichenanzahl ) angegeben werden können.
Wenn wir dann den ersten Datensatz lesen, kürzen wir stdin an der richtigen Stelle (also am Ende des ersten Datensatzes) und beenden ihn.
GNU sed
Mit GNU sed
können Sie Folgendes tun (vorausgesetzt, die Datei enthält keine NUL-Zeichen oder Folgen von Bytes, die keine gültigen Zeichen bilden - beides sollte für Textdateien gelten):
sed -Ez -i -- 's/^(.{1234}).*/\1/' "$file"
Dies ist jedoch weitaus weniger effizient, da die Datei vollständig gelesen, vollständig im Speicher abgelegt und eine neue Kopie geschrieben wird.
GNU awk
Gleiche mit GNU awk
:
awk -i inplace -v RS='^$' -e '{printf "%s", substr($0, 1, 1234)}' -E /dev/null "$file"
-e code -E /dev/null "$file"
Dies ist eine Möglichkeit, beliebige Dateinamen an zu übergeben gawk
RS='^$'
: Schlürfen Modus .
Shell eingebaut
Mit ksh93
, bash
oder zsh
(mit Muscheln ausgenommen zsh
, den Inhalt unter der Annahme nicht NUL enthalten Bytes):
content=$(cat < "$file" && echo .) &&
content=${content%.} &&
printf %s "${content:0:1234}" > "$file"
Mit zsh
:
read -k1234 -u0 s < $file &&
printf %s $s > $file
Oder:
zmodload zsh/mapfile
mapfile[$file]=${mapfile[$file][1,1234]}
Mit ksh93
oder bash
(Vorsicht, es ist falsch für Multi-Byte-Zeichen in mehreren Versionen vonbash
):
IFS= read -rN1234 s < "$file" &&
printf %s "$s" > "$file"
ksh93
Sie können die Datei auch direkt abschneiden, anstatt sie mit dem <>;
Umleitungsoperator neu zu schreiben :
IFS= read -rN1234 0<>; "$file"
iconv + head
Um die ersten 1234 Zeichen zu drucken , besteht eine andere Möglichkeit darin, in eine Kodierung mit einer festen Anzahl von Bytes pro Zeichen wie UTF32BE
/ zu konvertieren UCS-4
:
iconv -t UCS-4 < "$file" | head -c "$((1234 * 4))" | iconv -f UCS-4
head -c
ist nicht Standard, aber ziemlich häufig. Ein Standardäquivalent wäre dd bs=1 count="$((1234 * 4))"
jedoch weniger effizient, da es die Eingabe lesen und die Ausgabe byteweise schreiben würde¹. iconv
ist ein Standardbefehl, aber die Codierungsnamen sind nicht standardisiert, sodass Sie möglicherweise Systeme ohne findenUCS-4
Anmerkungen
Obwohl die Ausgabe höchstens 1234 Zeichen hat, ist sie möglicherweise kein gültiger Text, da sie möglicherweise in einer nicht begrenzten Zeile endet.
Beachten Sie auch, dass diese Lösungen zwar keinen Text in der Mitte eines Zeichens ausschneiden, ihn jedoch in der Mitte eines Diagrammsé
unterbrechen könnten , wie beispielsweise U + 0065 U + 0301 ( e
gefolgt von einem kombinierenden Akzent). oder Hangul Silbengrapheme in ihren zerlegten Formen.
¹ und bei der Pipe-Eingabe können Sie nur dann bs
zuverlässig Werte außer 1 verwenden, wenn Sie die iflag=fullblock
GNU-Erweiterung verwenden, da dd
kurze Lesevorgänge möglich sind, wenn die Pipe schneller gelesen wird, als sie iconv
gefüllt wird
cut
immer noch keine Mehrbyte-Zeichen unterstützt. Wenn es so wäre, könntest du es tuncut -zc-1234 | tr -d '\0'
.