Nehmen wir an, ich habe zwei Dateien mit beliebigen Bytes: ./delimiter
und ./data
.
Ich möchte ./data
bis zum ersten Vorkommen der Bytefolge in lesen (ausschließlich) ./delimiter
.
Wie würde ich dies mit Bash machen?
Beispiel:
- Inhalt von
./delimiter
world
- Inhalt von
./data
helloworld
- Erwartetes Ergebnis:
hello
Ähnliche/gleichwertige Frage:
Hinweis: read -d delim
löst mein Problem nicht, da nur ein einstelliges Trennzeichen und kein String unterstützt wird. Außerdem speichert es das Ergebnis in einer Variablen, und Variablen unterstützen keine NUL
Bytes. Ich möchte die Ausgabe auf stdout
.
Antwort1
Perl zur Rettung!
perl -e 'local $/;
open $de, "<", "delimiter" or die $!;
$/ = <$de>;
open $da, "<", "data" or die $!;
chomp( $first = <$da> );
print $first;'
Die spezielle Variable$/setzt den Eingabedatensatz-Trennzeichen, indemlokalWenn wir es tun, lesen wir die ganze Datei (auch "slurping" genannt). Dann verwenden wir den Rautenoperator, um aus der delimiter
Datei zu lesen, und setzen den Trenner auf den Inhalt. Dann lesen wir den ersten Datensatz aus der data
Datei,mampfenEntfernen Sie daraus den Datensatztrenner.
Antwort2
Mit zsh
(der einzigen Shell, die beliebige Bytefolgen in ihren Variablen speichern kann) können Sie unter der Annahme, dass es sich bei data
und delimiter
um reguläre (oder zumindest mmap()-fähige) Dateien handelt, Folgendes tun:
zmodload zsh/mapfile
set +o multibyte # necessary so sequences of bytes that
# happen to form valid characters may be
# broken in the middle if necessary.
firstpart=${mapfile[data]%%$mapfile[delimiter]*}
Oder:
zmodload zsh/mapfile
set +o multibyte # necessary so sequences of bytes that
# happen to form valid characters may be
# broken in the middle if necessary.
delimiter=$mapfile[delimiter]
parts=( ${(ps[$delimiter])mapfile[data]} )
firstpart=$parts[1]
(erwarten Sie nicht, dass es sehr effizient ist oder sich gut auf Dateien skalieren lässt, die größer als ein paar Hundert Megabyte sind).
Um diesen Teil wörtlich auszudrucken, verwenden Sie:
print -rn -- $firstpart
Oder
printf %s $firstpart