1.Zeile aus einer Datei auslesen

M

Mattze63

Hallo und guten Tag an alle,

ich habe ein Problem, das ich mit meinen sehr minimalen und noch dazu stark veralteten Kenntnissen der Shellprogrammierung nicht lösen kann.
Ich muß zur Fallunterscheidung in eine Eingangsdatei schauen, in dieser muß ich dann die ersten drei Zeichen der ersten Zeile auslesen um sie mit einer vorgegebenen Zeichenfolge zu vergleichen.
Bei positivem Match soll eine bestimmte Aktion ausgeführt werden.

Das ganze soll auf einem HP Unix funktionieren.
Ich habe schon geraume Zeit in den Forenbeiträgen gesucht, aber leider nichts gefunden.

Vielleicht kann mir ja jemand helfen.

Besten Dank vorab und Grüße

Matthias
 
Vielleicht

Code:
#!/bin/bash
if [ `dd if=datei bs=1 count=3` = "abc" ]; then
    echo "1"
else
    echo "2"
fi
 
Mit dd ist das aber schon sehr barbarisch, wie wärs mit "head -c 3"?
 
Code:
$ echo $'test\n123'|
$ perl -ne 'exit(/^abc/ ? 0 : 1)' && echo 'yay' || echo 'nej'
nej
$ echo $'abc\nfoo'|
$ perl -ne 'exit(/^abc/ ? 0 : 1)' && echo 'yay' || echo 'nej'
yay

Hat man gleich auch ne gute RE-Engine zur Hand und muss sich nicht mit sed-Pipes, command-Substitutions oder gar bash-Pattern-Matching rumschlagen.
I've got a fever and the only prescription is moar perl!
 
Code:
$ cat test
abcfoo
$ time for i in {1..1000}; do [ "$(head -c3 test|grep -o '^abc')" ]; done

real    0m15.162s
user    0m6.126s
sys     0m8.202s
$ time for i in {1..1000}; do perl -ne 'exit(/^abc/ ? 0 : 1)' test; done

real    0m9.516s
user    0m4.187s
sys     0m4.675s
Da dd nix von charsets weiß, vernachlässige ich das hier einfach mal...
Und ne schnellere Lösung mit head ist mir auch nicht eingefallen.
edit:
Mit ohne regex (und extra grep-pipe) gehts fixer:
Code:
$ time for i in {1..1000}; do [ x"$(head -c3 test)" = x"abc" ]; done

real    0m6.444s
user    0m2.810s
sys     0m3.305s
Aber halt nur string-Vergleich, wobei, bash-Patternmatch geht wohl auch fixer:
Code:
$ time for i in {1..1000}; do [[ x"$(head -c3 test)" =~ ^xabc ]]; done

real    0m6.846s
user    0m2.723s
sys     0m3.377s
Aber wegen diesen paar Sekunden sich gegen die durch perl gewährleistete Portabilität zu entscheiden, naja, nicht mein Bier. :)
 
Zuletzt bearbeitet:
Okay,

das hätte ich jetzt wirklich nicht gedacht. Man lernt nie aus!

Code:
~$: cat head.sh 

FORTUNE="Chuck Norris hat in seinem Leben zweimal gebadet - So entstanden das Rote- und das Tote Meer."

time for ((i=0; i<=1000; i++)); do head -c5 $FORTUNE 2> /dev/null > /dev/null; done

time for ((i=0; i<=1000; i++)); do dd if=$FORTUNE of=/dev/null bs=1 count=5 2> /dev/null > /dev/null; done

time for ((i=0; i<=1000; i++)); do echo $FORTUNE > perl -ne "exit(/^abcde/ ? 0 : 1)" 2> /dev/null > /dev/null; done

~$: ./head.sh 

real	0m2.282s
user	0m0.677s
sys	0m1.614s

real	0m2.393s
user	0m0.682s
sys	0m1.690s

real	0m0.250s
user	0m0.163s
sys	0m0.086s
 
Zuletzt bearbeitet:
Hehe, muss auch wenn überhaupt:
Code:
time for ((i=0; i<=1000; i++)); do perl -ne "exit(/^abcde/ ? 0 : 1)" $FORTUNE 2> /dev/null > /dev/null; done
heißen¹, weil du sonst nur ein echo-Kommando hast. Dann ist es (bei mir zumindest) auch langsamer als head und dd, was ja auch verständlich ist.. (Aber bei head und dd hörts ja nicht auf, man muss ja den output irgendwie weiterverarbeiten in einem neunen Prozess.)
Warum zum Beispiel meine gepostete head-grep-pipe Lösung so miserabel abschneidet ist recht simpel: es werden sehr viele Prozesse gespawnt.
Code:
[ "$(head -c3 test|grep -o '^abc')" ]
Ein Prozess für test ([), einer für head und einer für grep. Und dann werden command-Substitutions und pipes in subshells ausgeführt, also nochmal zwei extra Bash-Instanzen. Wenn ich mich nicht verzählt hab wären das dann laut Eva Zwerg fünf Prozesse gegen einen (perl). Da gut abzuschneiden ist ja fast schon schummeln. Aber naja.
edit: test ist ja built-in und nicht mehr ein extra Prozess wie früher, ganz vergessen. Aber immernoch 4 vs. 1.


Man kann das ganze übrigens noch mystischer schreiben:
Code:
perl -ne 'exit !/^abc/'
shell true und false Werte (exit-Values) sind ja quasi vertauscht im Gegensatz zu "richtigen Sprachen".

edit:
ad 1: so muss es auch nicht heißen, hab mir mal deine head.sh angeschaut...
Sagen wirs mal so: wer stdout und stderr jeweils einen fetten /dev/null-Knebel reinprügelt muss sich nicht über ausbleibende Schreie bei der Vergewaltigung diverser Prozesse wundern.
 
Zuletzt bearbeitet:
Zurück
Oben