1
display_menu() { section="$1" grep -5 -h "\[$section\]" datei.txt|sh } so kannst du deine Menues anzeigen lassen (-<Zahl> Option gibts bei meinem grep nicht, ist wohl die Anzahl Zeilen?) 2
: Geht z.B. so: : $ find . -type d -maxdepth 1 | sort ; \ : find . \! -type d -maxdepth 1 | sort ^^^^^^^^^^^ Die Option -maxdepth ist eine "typische" GNU-find Option. Im allgemeinen funktioniert dies nicht (z.B. kennen weder das Solaris noch das HP-UX find diese Option). Die Loesung von Cornelius mit dem ls -F ist da wesentlich portabler und wohl auch performanter. Das -maxdepth klappte bei mir hier im Büro unter Solaris in der Tat nicht. Holger hatte es ja schon "angekündigt". Somit ist ein ls -l | grep '/$'; ls -l | grep -v '/$' für mich fast perfekt. Fast, weil mich darin noch das "total 390" (o.ä.) stört, welches nach dem ersten ls ausgegeben wird. Aber daran arbeite ich noch ... 3
>> Wie kann ich mit awk das aktuelle Datum ausgeben? > strftime AFAIK eine gawk erweiterung, das nawk auf dem Solaris 5.5.1 vor mir weiss jedefalls nichts davon. $ echo foo | oawk 'BEGIN { print "'"`date`"'" }' Wed Jun 13 00:50:49 CEST 2001 $ Häßlich, läuft aber bis v7. Geht auch per Shell-Variable, falls man es mehrfach braucht: 4
Bei xargs denken wir an die Option -0 und bei find an die Option -print0, die es leider nur bei GNU-xargs und GNU-find gibt? 5
>Exp. ist? Ist das von der Shell abhaengig? Ja. Normalerweise erfolgt das Globbing nicht mit regulären Ausdrücken. Du möchtest "find . -[i]regex 'bla' -maxdepth 1 | xargs echo" verwenden. (echo später durch rm -vf ersetzen.) 6
Bitte kein »==« bei »test« verwenden, diese im Ergebnis nutzlose C-Analogie ist nirgendwo standardisiert. An dieser Stelle sollte man nicht nach Geschmack urteilen. 7
Die SHELL-Zeile ist haklig. Der Wert ist nicht systemübergreifend vorzugeben, aber ohne läuft es auf Solaris usw. nicht. Mit /usr/bin/ksh hat man m.E. am meisten Chancen. > Stimmt, wenn man keine GNU-findutils, die --null verstehen, hat, sollte > man xargs _nur_ fuer Aktionen, welche die gefundenen Dateien nicht > veraendern, einsetzen (grep, cat, ...) und sonst -exec verwenden. > Die eigentliche Überraschung ist aber, daß SVr4 dieses Verhalten schon > seit einer Ewigkeit undokumentiert implementiert hat, wie ich von > Solaris und UnixWare her bestätigen kann. Das gilt tatsächlich für alle Solaris 2+. Abgesehen von 2.5 bis 8 habe ich mir dann noch die find-Versionen von Solaris 2.1 und 2.3 (auf 2.5) angesehen, die es auch schon beherrschen. (SunOS4.1.4 kann es wie erwartet »noch« nicht). Auf den übrigen, die ich probiert habe (HP-UX 10.10/20, IRIX 6.5.x, AIX 4.3, OSF1/V4.0B) geht es leider auch nicht. Von Irix hätte ich es eigentlich noch am ehesten erwartet, allerdings stammt es lt. <http://perso.wanadoo.fr/levenez/unix/> im wesentlichen von SVR3.0 (und MIPS OS) ab, Solaris und UnixWare hingegen aber eben von SVR4. > Auf den übrigen, die ich probiert habe (HP-UX 10.10/20, IRIX 6.5.x, > AIX 4.3, OSF1/V4.0B) geht es leider auch nicht. HP-UX 11 hingegen kann und dokumentiert es auch:
AUTOR: sven.mascheck@student.uni-ulm.de 8
> printf "\0377" Das soll offenbar GNU printf oder bash sein, welche hier gegen ISO/IEC 9945-2:1993, 4.50.7, Abschnitt 3, S. 395, Z. 8205-8207 verstoßen: # [...] \ddd, where ddd is a one-, two- or three-digit octal number, # shall be written as a byte with the numeric value specified by the # octal number. GNU printf: $ printf "\0377" ÿ$ korrekt (ksh93, Solaris), das Steuerzeichen US ist nicht zu erkennen: $ printf "\0377" 7$ also zwei Zeichen, ASCII 037 und ASCII 067, entsprechend zur C-Syntax. Ein »ÿ« erhielte man mit »printf "\377"«, welches das tumbe externe GNU printf (sh-utils 2.0) gar nicht verarbeiten kann. 9
Ich würde sowieso davon abzuraten, nicht-Textdaten (siehe das Zitat in <3B067286.H61TJUQS@bigfoot.de>) mit der Shell zu bearbeiten oder zu erzeugen, selbst wenn es mal funktioniert; mehr als ein fragwürdiger Hack wird das nie. Nimm Perl oder C. 10
> source qt3env Bash-Erweiterung ohne erkennbaren Nutzen. Portabel ist . qt3env Falls das Skript im aktuellen Verzeichnis liegt, besser . ./qt3env Die Eigenheit der bash, das Skript auch im aktuellen Verzeichnis zu suchen, verstößt gegen POSIX.2, 3.14.4, wonach nur in $PATH zu suchen ist. 11
> grep 'Suchbegriff1\|Suchbegriff2\|...' datei1 datei2 datei3 ... Vollständig proprietäre GNU-regexp-Erweiterung. Jede andere Methode ist vorzuziehen. POSIX.2: grep -e Suchbegriff1 -e Suchbegriff2 -e ... datei1 datei2 datei3 ... grep -E 'Suchbegriff1|Suchbegriff2|...' datei1 datei2 datei3 ... Traditionell und hochportabel: egrep 'Suchbegriff1|Suchbegriff2|...' datei1 datei2 datei3 ... 12
>> a) Du benutzt "read" ohne Variable. Dadurch wird die ganze Zeile >> inkl. Leerzeichen am Anfang und Ende in die Variable $REPLY > ^^^^^^^^^ >> eingelesen. > [...] > > Nö. Es ging im Thread um die bash, und da geht es: >>> #! /bin/bash >> >>Mach mal das Leerzeichen weg. > > [x] das willst du nicht, wenns auch auf exotischen systemen > laufen soll. Hat denn inzwischen jemand herausgefunden, um welche exotischen Systeme es sich dabei eigentlich handelt? Der Hinweis auf 4.2BSD im autoconf-Manual ist fragwürdig <3944C409.R311S6RQ@bigfoot.de>; ein weiteres Gerücht spricht von UnixWare, was aber zumindest auf die mir bekannten 2.1er-Versionen nicht zutrifft. Gerüchten zufolge Ultrix, kann ich aber nicht verifizieren. Eventuell kommt auch IRIX 4 in Frage, kann ich aber auch gerade nicht verifizieren. 13
> Wenn ich das Kommando "sleep 1000" mit Ctrl-Z suspende, dann mit "bg" in den > Hintergrund schicke, terminiert sleep sofort Das eigentlich wichtige hast Du vergessen: Offenbar arbeitest Du auf Linux. <http://www.uni-ulm.de/~s_smasch/nanosleep_linux/> · »Bug« von sleep(1) · einigermaßen eigenwilliges GNU sleep(3) Die ksh93 hat übrigens ein sleep built-in, das vernünftig funktioniert.
AUTOR: sven.mascheck@student.uni-ulm.de 14
> "Ungültiger Dateideskriptor". Die Man page legt aber nahe, daß > die KSH das können sollte, also was mache ich falsch? > > 4<test.txt exec 4<test.txt 15
Was willst Du mir damit sagen ? Dass das simple echo $[1+2] in _deiner_ shell nicht klappt, da Du eine andere benutzt ? Im großen und ganzen ist das eine private Macke von David Korn, die leider all zu oft bedenkenlos mitgespielt wird. Die ernstzunehmenden Gründe für $(...) haben nur selten einen Stand gegen die Portabilität von `...`. Ob man das unterschiedliche Quoting innerhalb nun als Bug oder als Feature auffaßt, ist entweder situationsabhängig oder eine pure Geschmacksfrage. Die Shell hat eben keine konsistente Grammatik, 16
> echo "$1" | grep -q '^[[:digit:]]\+$' && echo "$1" ^^ ^^^^^^^^^ ^^ Zweimal beschränkte Portabilität, einmal proprietäre GNU-RE. 17
> nummer sicher, da z.b. Solaris awk (/usr/bin/awk) kein > toupper()/tolower() kennt (ok, Solaris kennt auch eher kein > mawk, dafuer aber nawk...). Eben; ich fände es sinnvoller, verbal auf das Sprachlevel hinzuweisen, als Präfixe vor awk zu setzen. »nawk« kann schließlich alles von SVr3.1 bis POSIX.2 sein, und nawk(BU_CMD) der SVID3 enthält noch kein tolower(). > Danke für die Beispiele - leider hab' ich's immer noch nicht geschafft, > die auf der Arbeit mit Solaris' awk auszuprobieren. Hier (zuhause, > GNU/Linux), schafft einzig bwk's "one true awk" das erste Beispiel, mawk > und gawk jammern über syntax/parse errors. Das zweite Beispiel läuft mit > allen drei Awks hier (und liefert nichts, was wohl beabsichtigt ist). Das erste Beispiel ist syntaktisch nicht mehr definiert, das zweite liefert mit älteren awks »yes«, weil die Operatoren dort z.T. eine andere Präzedenz haben. Gerade letzteres ist beim Portieren sehr heimtückisch. So viele gibt es da doch gar nicht. Solaris hat ein /usr/bin mit System V-artigen Tools und ein allerdings wesentlich schlechter gepflegtes /usr/ucb mit BSD-artigen Tools. Was außer vielleicht XENIX könnte man noch guten Gewissens Unix-Tradition nennen? > Wie Du oben gezeigt hast, ist /usr/xpg4/bin/awk (oder > nawk) nicht ganz kompatibel zum Ur-awk (btw: gibt's Quellen dafür, damit > ich meine Skripts auch mal dagegen testen könnte?). <http://shop.caldera.com/caldera/ancient.html> <http://www.sun.com/solaris/source> 18
> - gibts z.B. einen Standard, der vorschreibt, dass "sort"¹ ab 2048 > Zeichen Zeilenlänge die Grätsche machen kann/soll/muss? Ja, »kann«. ISO/IEC 9945-2:1993, 4.58.5.2: # The input files shall be text files, except that the sort utility # shall add a <newline> to the end of a file ending with an incomplete # last line. Das heißt, bei mehr als 2048 Zeichen pro Zeile bewegst Du Dich auf unsicherem Terrain. 19
~% date +%s -d '01/01/1970 00:00:01 GMT' ObDisclaimer: 1. Die Frage gehoert nach de.comp.os.unix.shell (X-Post & Followup). 2. Die obige Loesung funktioniert nur mit GNU date. Eine POSIX- Loesung gibt es m.W. nicht. 20
> Also ich würde das wohl eher so machen: > > for i in `seq -w 1 10`; do > echo $i > done > > 'seq' ist ein (GNU?-)Programm mit dem man Sequenzen von Zahlen ausgibt. > Der '-w'-Flag dient dazu, daß die Nummern mit '0' aufgefüllt werden, > wenn nötig. Wie portabel das allerdings ist, weiß ich nicht. Nicht portabel. Schon FreeBSD hat kein seq, HP-UX auch nicht. 21
> GNU grep hat eine quiet option -q, dann gehts auch so: »-q« ist POSIX.2, nur im traditionellen »grep« nicht enthalten. > Analog haben egrep und fgrep die silent option -s. Nein, »-s« bewirkt nur die Unterdrückung von Fehlermeldungen. Das Verhalten von v7 und älteren BSDs in diesem Fall ist Geschichte, standardisiert ist die System V-Semantik. 22
> ich habe aus einem Logfile verschiedene Uhrzeiten, von denen ich (mit > bash-Mitteln, nicht mit Perl) eine bestimmte Anzahl Sekunden abziehen > möchte, d.h. Uhrzeit: 08:25:14, 185 Sekunden abziehen, neue Uhrzeit: > 08:22:09 > > Geht das ohne grossartige Rechenoperationen auch relativ einfach (mit > date oder sowas) ? #!/usr/bin/awk -f # tdiff: gibt Differenz zweier Uhrzeiten aus BEGIN { if ( ARGC != 3 ) { printf "Aufruf: tdiff Zeit1 Zeit2\n"; exit 1; } t1 = ARGV[1]; t2 = ARGV[2]; split(t1, ta1, /:/); split(t2, ta2, /:/); t1 = 3600 * ta1[1] + 60 * ta1[2] + ta1[3]; t2 = 3600 * ta2[1] + 60 * ta2[2] + ta2[3]; if (t1 > 86400 || t2 > 86400) { printf "falscher Wertebereich!\n"; exit 1; } res = t1 - t2; if (res < 0) { res *= -1; vz="-"; } printf "%c%.2d:%.2d:%.2d\n", \ vz, res/3600, (res%3600)/60, (res%3600)%60; exit 0; } 23
> Es zeigt sich aber leider keine Wirkung. Was mache ich falsch? sed arbeitet zeilenorientiert, du willst entweder vorher alle \n rauswerfen (| td -d '\n') oder nicht sed verwenden. 24
date +%s zeigt mir den aktuellen timestamp, wie kann ich jetzt mit diesem timestamp die zugehörige Uhrzeit anzeigen? z.B. date +%H.%M.%S -d 'timestamp' oder so... 25
> $ ls -1tr | head -n 1 Wobei die "1" im ls nicht notwendig ist. Und mein head nimmt auch "-1" anstatt "-n 1", aber das kann natürlich bei den Versionen unterschiedlich sein. 26
> also eigetnlich sollte das doch ganz einfach sein, ich möchte von dem > was date mir zurückliefert einen Tag abziehen, leider gehts mit -1 > nicht, also wie bekomme ich gestern?? Wie es z. B. mit GNU date geht, wurde hier vor ein paar Tagen durchgekaut, siehe: Ja, ich weiß, hab den Thread auch gelesen. Wir haben aber kein GNU, wir benutzen DEC-Unix (true 64) und kriegens damit einfach nicht hin. Irgend eine Idee? 27
wie kann ich in einer bourne-artigen Shell (ich benutze GNU bash, wüßte aber gerne eine möglichst portable Lösung) erreichen, dass der Exitcode einer Pipeline gleich dem Exitcode des *ersten* Kommandos der Pipeline ist? ich wuesste jetzt nur diese Loesung: 28
$ touch foo $ tempfile=`/usr/bin/mktemp -t tar` ; \ > tar cf - foo 2> $tempfile | \ > bzip2 > foo.tar.bz2 ; \ > if [ -s $tempfile ] ; then echo "hi" ; else echo "ho" ; fi ho Das kannst du nicht erreichen. Jedenfalls nicht portabel. 29
> kurz vorweg zur Option "--exclude": > Diese existiert nur in gtar (GNU-Tar) und ist nicht POSIX-konform. > [...] >> find -type f | xargs tar -cf archif.tar ??? Schwätzer. Tatsächlich ist das von Dir vorgeschlagene »find -type f« nicht durch POSIX abgedeckt. Ein tar-Utility ist hingegen in keinem der POSIX-Standards spezifiziert, sondern lediglich das Format der Archive. Eine POSIX-Variante Deines Vorschlages lautete also find . -type f | pax -w -x ustar -f archiv.tar aber das will man auch nicht benutzen, weil es ebenso wie der erste Versuch bei Dateinamen mit enthaltenem Whitespace krepiert. 30
> sed -n '/^[^ ]\{7\}\($\|[ ]\)/p' Leider nicht portabel. Habs eben unter SunOS 5.7 ausprobiert. Gibt auch keine Fehlermeldung und nichts. Ich tippe mal auf die {} Metacharacter als Ursache. Bei GNU-sed klappts natürlich. Hätte gern mal gewusst, ob {} nur mit GNU-sed/egrep funktioniert oder auch mit anderen Varianten. 31
> $ echo foo\\tbar > foo bar > $ echo 'foo\tbar' > foo bar Komische Shell. $ echo foo\\tbar foo\tbar $ echo -e foo\\tbar foo bar Eine SUSv2-Shell muß das so machen. > Wenn die bash schon nicht SUSv2-kompatibel ist, ist es echo bestimmt > auch nicht ;-) 32
> Wenn die bash schon nicht SUSv2-kompatibel ist, ist es echo bestimmt > auch nicht ;-) Mal ne Frage am Rande: Welche Shell *ist* es denn? Es nützt einem eine Spezifikation leider recht wenig, wenn die diversen in Umlauf befindlichen Shells dieser nicht entsprechen. Das ist nicht als Kritik an der SUSv2 gemeint, eher als Kritik an den nicht-konformen Shells. Wobei aber auch wieder zu berücksichtigen ist, dass Standards gewöhnlich auf Eigenschaften existierender Systeme aufbauen, in der *Hoffnung* einer Verallgemeinerung. Ein Teufelskreis also. Bleibt dann häufig nur die Besinnung auf den kleinsten gemeinsamen Nenner, wenn man portabel programmieren will. 33
juergen@anna:~ > eval tag${a}tag${b}=200 juergen@anna:~ > echo $tag001tag002 200 Wenn es mal ne FAQ zu dieser Newsgroups gibt, dann gehören Fragen, die sich mit »eval« beantworten lassen, auf der Liste ganz nach oben. ;-) 34
> >> Wie kann ich einen String, der in einer Variable steht (und zur Zeit > >> gemischte Groß- und Kleinschreibung hat) auf Großbuchstaben umwandeln? > > > >echo $var | tr '[a-z]' '[A-Z]' > > verfeinert: > > var=`eval echo \"$var\" | tr '[a-z]' '[A-Z]'` > > So funktioiniert das auch mit fuehrenden und folgenden leerzeichen. Schöne Lösung, nur leider falsch. Test mit: var=" a b c " # 2 Blanks zwischen a und b var=`eval echo \"$var\" | tr '[a-z]' '[A-Z]'` echo "$var" zsh: Klappt. pdksh, bash und SunOS 5.7 /bin/ksh: > A B C < (Ein Blank unterschlagen) Es klappt dagegen (ohne eval) und auf bash, zsh, pdksh und SunOS 5.7 /bin/ksh: var=`echo "$var" | tr '[a-z]' '[A-Z]'` Und da wir schon dabei sind: var=`echo "$var" | tr '[:lower:]' '[:upper:]'` ...Wie war das noch gleich, mit der FAQ für eval? 35
> Ich möchte bei einem bestimmten event das datum möglichst als Zahl > speichern und > dann bei einem ähnlichen event den zeitunterschied bestimmen, gibt es da > eine einfache Möglichkeit ? man 1 date man 1 awk GNU-Awk hat eine Funktion systime(), die wohl genau das ist, was du brauchst. Mit date und awk kannst du dir was entsprechendes zusammenbasteln, falls du kein GNU-Awk hast und/oder die Lösung portabel sein muss. 36
Es geht um das folgende eigentlich eher triviale Konstrukt: echo a b | read x y echo "x=$x y=$y" Ergibt x=a y=b Zumindest sollte man das erwarten, und es funktioniert auch bei ksh93 und zsh. Bei pdksh und bash bekomme ich jedoch x= y= Ich gehe mal davon aus, du beziehst dich auf (SUSv2, xcu/chap2.html#tag_001_012): :Some systems have implemented the last stage of a pipeline in the current :environment so that commands such as: : :command | read foo : : set variable foo in the current environment. This extension is allowed, :but not required; therefore, a shell programmer should consider a pipeline :to be in a subshell environment, but not depend on it. Dies ist denn auch wohl schon des Rätsels Lösung. Ich finde es trotzdem bemerkenswert, dass cat file | read foo sich um so viel anders verhalten _kann_ als read foo < file Aber selbst SUSv2 definiert das Verhalten ja nicht exakt, sondern läßt beide Möglichkeiten zu. Aufpassen ist hier also angebracht. 37
> ich hab hier ein skript, das zeilenweise eine Datei > liest und abhängig vom Inhalt Variablen erzeugt und > ihnen Werte zuweisst. Hier ein Stück code: > > while read foo; do > #auswertung und variablenzuweisung > done < $FILE > > Unter der bash funktioniert das auch ganz gut, aber > die solaris-shell erzeugt eine Subshell wenn eine > datei "eingepiped" wird. 38
> find -exec sh -c "ls {} | wc" \; Erstens fehlt da die Pfadangabe und zweitens ist die Behandlung von {} implementationsabhängig, wenn es nicht als einzelnes Argument auftaucht. 39
> Bisher nehme ich foo=$(bar). Sollte man besser foo=`bar` nehmen? Das kommt darauf an, ob du auf Bourne-Shell-Kompatibilität angewiesen bist. Dann bist du mit foo=`bar` definitiv auf der sicheren Seite. Wenn du dagegen eine "POSIX-Shell" verwendest (das sind z.Zt. ksh88/93, zsh, bash, alle mehr oder weniger, die ksh wohl am ehesten), dann hast du auch die Option foo=$(bar) Wenn du eh viele über Bourne-Shell hinausgehende (POSIX-)Konstrukte verwendest, ist gegen $() nicht viel einzuwenden, außer, dass es eine 40
>Bei der Answeisung > >ff="!R!" > >bekomme ich immer die Fehlermeldung : bash: !R!: event not found >Was bedeutet das ???? >Ich muss einer Variablen den Wert zuweisen um ein Formfeed durch >"!R!\nPAGE;\nEXIT;" zu ersetzen. Das wollte ich mit "tr" machen. man bash, insb. nach der set option -H suchen. (set +H schaltet diesen csh-ismus ab) 41
>btw... ich habe auf zwei Solaris-Kisten versucht <NEWLINE> mit zu ersetzen, >auf der einen klappte das mit tr "\n" " " wunderbar, auf der anderen wollte >er partout eckige Klammern, also ["\n"] haben. > >Verschiedene tr Versionen? stty-Setzungen? Verschiedene Shells. 42
> <kommando> | awk -f script.awk -v TMP=$SHELLVAR > > Nur ist die $SHELLVAR nicht leer, wird aber dennoch nicht von awk > richtig ausgelesen, da in dem script.awk lifert mir > > print "SHELLVAR ist" TMP > > absolut nichts ausser dem was in den Gaensefuesschen steht... was mach > ich falsch? "awk" ist auf Solaris /usr/bin/awk oder /bin/awk, und das versteht die -v -Option nicht. Was Du suchst, findest Du unter Solaris als /usr/xpg4/bin/awk oder "nawk". 43
4<test.txt read zeile <&4 echo "$zeile" read zeile <&4 echo "$zeile" Dieses ist ein Beispiel aus einem Buch, wodurch ich die Datei test.txt zeilenweise einlesen können soll. Leider endet der Versuch mit einem "Bad File Descriptor" Laut Manpage Bash kann ich keinen Fehler in der Syntax finden. exec 4<test.txt Ansonsten ist die Umleitung nur für die Dauer dieses einen (leeren) Kommandos gültig. 44
> Mit welchen Programmen kann ich das innerhalb eines Shell-Skriptes > machen, bzw. geht das ueberhaupt und wie? wget, lynx -source . Das Aetzendste dabei ist idR, sich durch das zurueckgegebene HTML zu parsen, um die wichtigen Dinge zu isolieren. Alternativ kann man dafuer Perl verwenden, es handelt sich dann aber nicht mehr um ein Shellscript :-) 45
Wenn du nur ein _einzelnes_ Zeichen lesen willst, brauchst du natürlich _keine_ Schleife... stty -icanon printf "Bitte Taste drücken " key=$(dd bs=1 count=1 2>/dev/null) # oder key=`...` echo stty icanon 46
>>> Das ist sehr gewagt! Es soll Syteme geben, wo es eine /bin/sh gibt und >>> nicht, wie bei SuSE /bin/sh ein Link auf /bin/bash ist. > > <Gebetsmühle> /bin/sh *kann* nicht nur alles mögliche sein - dem ist > tatsächlich auch so.
AUTOR: sven.mascheck@student.uni-ulm.de 47
> usage () > { > echo "usage: $0 args..." > } > > Dabei habe ich festgestellt, daß manche Shells hier > $0 durch "usage" (ksh auf AIX 3.2) ersetzen, während andere > (bash, (pd)ksh auf Linux, sh auf AIX 3.2) nur die > Positionsparameter ab $1 bei einem Funktionsaufruf verändern. > > Meine Frage: Ist dieses Verhalten der ksh auf AIX 3.2 > a) ein bug oder Nein, ein Feature älterer (prä-POSIX.2-) Korn-Shells und auch bei der aktuellen ksh93 l+ noch, wenn man »function« zur Funktionsdefinition verwendet. Die ksh von SunOS 5.8 ändert $0 allerdings in keinem Fall: Shell foo() { ... function foo { ... -------------------------------------------------------------------- SVr2-Bourne Skriptname n/a SVr4-Bourne Skriptname n/a SVr4.2-Bourne Skriptname n/a ksh86 a Funktionsname Funktionsname ksh88 h, OpenUNIX 8 Funktionsname Funktionsname ksh88 i, SunOS 5.8 Skriptname Skriptname ksh93 e-SCO, OpenUNIX 8 Skriptname Funktionsname ksh93 l+ Skriptname Funktionsname pdksh 5.2.14 Skriptname Funktionsname bash 1.14.7 Skriptname Skriptname bash 2.05 Skriptname Skriptname ash, RedHat 7.1 Skriptname n/a > b) im Standard nicht festgeleg. ISO/IEC 9945-2:1993(E), 3.9.5, p. 143: # The special parameter 0 shall be unchanged. Aber wenn Du eine ältere ksh aufrufst, bekommst Du eben eine ältere ksh. 48
>> [M-ksh88f] >> Sie ist dort als /bin/sh und /bin/ksh installiert, >> weshalb ich das Verhalten überprüfenswert fand. > > Unter dem Gesichtspunkt auch noch: > > ksh88f IRIX 6.5 (argv[0]: sh) Funktionsname Funktionsname > (argv[0]: ksh) Skriptname Skriptname
AUTOR: sven.mascheck@student.uni-ulm.de 49
>> [ ksh88f IRIX 6.5 (argv[0]: »sh« vs »ksh«) ] > So wie ich dich verstehe, ist das gleiche Binary > einmal als »sh« und einmal als »ksh« installiert. ...und zwar als /sbin/sh. Alles übrige (/bin/, /usr/bin/*sh) sind diverse Softlinks. > Dass in Abhängigkeit von argv[0] unterschiedliches Verhalten des > gleichen Binaries erreicht werden kann, ist klar. Was mir aber nicht > klar ist, wozu das gut sein soll. Der wichtigste Punkt ist wohl, daß ksh ja »erst« in IRIX 6.4 als System-Shell eingeführt wurde, und sh(1) meint dazu anfangs nur # To retain some backward compatibility to the Bourne shell, certain # Korn shell features are controlled by [...] Die früher als System-Shell installierte Bourne-Shell wird ja weiterhin als bsh/jsh(1) mitgeliefert, aber sobald diese eben nicht mehr als sh installiert ist, wird man sie nur noch in Spezialfällen verwenden. Ich habe mir diese ksh im Bourne-kompatiblen Modus noch nicht genauer angesehen, und obiges Zitat läßt ja gezielt viel Freiraum. Es geht sicher nicht um eine perfekte Bourne-Imitation, denn dann wäre ein Wrapper-Mechanismus wohl noch sinnvoller, wie z.B. bei OSF1, auf dem fork()/exec() (zu Bourne- oder POSIX- Shell) von $BIN_SH beeinflußt wird. Statt dessen geht es offenbar nur um einige Probleme mit der Rückwärts- kompatibilität der ksh - und damit z.B. um existierende Skripte. Einiges ist in der Manpage unter »COMPATIBILITY ISSUES« aufgelistet: spezielles Verhalten der Builtins wie unset, test, kill, chdir, false sowie dem Integer-Typ von einigen Variablen in der ksh. <http://reality.sgi.com/> ist seit dem 15. diesen Monats ja leider abgeschaltet. Die Manpage gibt es aber noch an diversen Stellen, wie z.B. <http://conx.bu.edu/cgi-bin/perl/manscript?sh(1)> An sich ist Verhalten gemäß argv[0] ja nicht unüblich (wenn auch nicht unumstritten), siehe softlinks wie »jsh«, »rksh« (oder auch »ex/vi«). (Und speziell die ksh hält sich da auch nicht zurück: z.B. kann man sie prinzipiell überhaupt nur via argv[0] als eine »login shell« aufrufen.) > Kann man unterschiedliches Verhalten nicht schon bei der Compilierung > erreichen, z.B. durch entsprechende Präprozessor-Anweisungen? Dadurch > dürfte doch ein wesentlich kompakteres, und darüber hinaus schnelleres > »sh«-Binary zu erziehlen sein. Die mögliche Geschwindigkeitseinbuße des neuen Mechanismus wird höchstens zweitrangig gewesen sein. Achja, das Binary ist übrigens zudem statisch gelinkt und hat (auf 6.5.12f) 696440 bytes (weil ksh88 selbst ja recht schlank ist). Es scheint, daß SGI vor allem an einem möglichst reibungslosen Übergang von Bourne- zu Korn-Shell interessiert war. Ich selbst habe aber noch nie eine Umstellung der System-Shell erlebt und weiß nicht, bis zu welchem Grad diese Spezial-ksh tatsächlich notwendig war.
AUTOR: sven.mascheck@student.uni-ulm.de 50
> ich habe einige Dateien mit Leerzeichen im Dateinamen. Ich möchte diese > durch einen Underscore ersetzen. Kann mir jemand vielleicht einen Tipp > geben wie ich das anstellen kann. Ich habe schon ein bisschen mit sed > herum experimentiert und auf Google gesucht. Die Ergebnisse behandeln > leider alle das Problem einer Datei mit Leerzeichen, ich möchte aber den > Dateinamen ändern. Sagt mal, Leute, *lest* ihr eigentlich die NGs, die ihr abonniert habt? Skurril finde ich das schon, da ist in den letzten 3 Tagen *exakt* das gleiche Thema in eigenem Thread <3BB34873.75965DCF@euroscript-ls.de> ff. so ziemlich von vorne bis hinten durchgekaut worden, und jetzt ... 51
> ed dateiname < <EOF > \$d > wq > EOF »w« genügt vollkommen, da ed die Ausführung beim Dateiende auf stdin sowieso abbricht. »wq« ist proprietäres Zeug, das man nicht benutzen will. 52
> >> > Ich muss nur wissen, wie ich den Wert einer Variable um ein erhoehen > >> > kann. > >> > >> Wie man mit der Shell rechnet, kommt doch hier fast jeden Tag: > >> > >> $bla=$(($bla+1)) > > > >Da ist ein $ zuviel. Ausserdem kann das die SunOS shell nicht, > >weswegen man besser expr(1) nimmt. > > ksh@sun$ bla=1 > ksh@sun$ echo $(($bla+1)) > 2 > > SunOS 5.8, shell ist /bin/ksh. Klar gibts auch fuer SunOS massig shells, die das koennen. Aber /bin/sh kanns nicht, und das ist fuer portable Skripte das einzige relevante. Auf der Kommandozeile moechte wohl eh nie jemand mit der Shell rumrechnen. 53
> mit sleep 1 kann man wohl eine Sekunde Pause > erreichen. Aber wie bekomme ich eine halbe > Sekunde hin. Bei mir geht sleep 0.5, aber die Manpage meint dazu The sleep command will accept and honor a non-integer number of specified seconds (with a . character as a decimal point). This is a non- portable extension, and its use will nearly guarantee that a shell script will not execute properly on another system. Eine portable Möglichkeit gibt es afaik nicht, es sei denn Du schreibst Dir selber ein Programm dafür (man 2 nanosleep). 54
> for zeile in `cat datei` > do > blubber $zeile > done Keine gute Idee. Wenn die Datei sehr groß ist, fliegt Dir das um die Ohren: Dann wird eine gigantische Variable angelegt, die im ungünstigsten Fall nichtmal mehr in den virtuellen Speicher paßt. Je nach OS sind die Folgen mehr oder weniger fatal. 55
Gibt es einen Weg Dezimalzahlen in Hexadezimalzahlen umzuwandeln? Der umgekehrte Weg ist ja z.B. echo $((16#4f)) 79 Gibt es da eine Möglichkeit? 56
einem shellscript lösen wuerde, weil es > 2500 dateien betrifft: jetziges format : test01082001_0711.jpg (testDDMMYYYY_HHmm.jpg) erwuenschtes format 08012001_0711.jpg (MMDDYYYY_HHmm.jpg) test rausschmeissen funktioniert ja schon, aber den dreher im namen krieg ich nicht hin. bis jetz habe ich: for a in test*.jpg do mv $a ${a##test} done hat irgendjemand vielleicht eine idee, wie das klappen könnte ? 57
> while read ZEILE > do > echo $ZEILE > ssh irgendeinrechner ls > done < dateiname > Dann gibt er genau die erste Zeile der Datei 'dateiname' aus, > macht auch dem Rechner 'irgendeinrechner' das ls und das > wars dann. Vermutlich krallt sich ssh einfach die komplette Eingabe und schickt sie an 'irgendeinrechner'. Daß der die gar nicht haben will, interessiert ssh erstmal nicht. > Eigentlich moechte ich ja, dass das ls so oft gemacht wird, wie > Zeilen in der Datei 'dateiname' sind. > Was mache ich da falsch? Probiers mal so: exec 5<&0 # stdin auf Kanal 5 verbiegen while read ZEILE do echo $ZEILE ssh irgendeinrechner ls <&5 # ssh bekommt das stdin des Scripts done < dateiname exec 5<&- # Kanal 5 schließen 58
>Ist i=$[i+1] bzw. i=$((i+1)) bash-spezifisch oder funktioniert das ^^^^^^^^^ Das ist bash-spezifisch, und funktioniert idR. nicht mit anderen shells. ^^^^^^^^^^ Dieses ist hingegen standardisiert. 59
> Wie kann ich in einem String das erste Zeichen testen bzw. ermitteln? echo "hello world" | awk '{ print substr($0,1,1) }' echo "hallo"| sed 's/^\(.\).*/\1/' 60
>>wie kann ich die immer gleine Zeichenfolge >>"-1000" an das Ende einer jeden Zeile stellen >>und "#" davor ?? > > while read line > do > echo "#$line -1000" > done < datei Das verschluckt leading whitespace, trailing whitespace und Backslashes bzw. hängt Zeilen aneinander, falls letzterer am Ende steht. Schlecht geschlafen? Oder habe ich die versteckte Botschaft übersehen? 61
>> echo Test >> $logfile hängt den Output an das Ende des Files. >> Was muss ich tun, damit er als erste Zeile im Logfile erscheint? > > Eine Möglichkeit wäre vielleicht mit »ed«: > > logtext=`command` > > ed - $logfile < <END > 0a > $logtext > . > w > END Irgendwie glaube ich, dass die Performance-maessig deutlichst suboptimal sein duerfte. Ausserdem belege ich Logs auf ext2 gerne mit append only 62
>> wie kann man ein einziges Zeichen, von einem >> Platz an den anderen verschieben? Ich würde >> gerne das '-' nach vorne verlegen, aber nur >> dann, wenn hinten auch ein '-' vorhanden ist. >> Ich dachte da an sed. Beispiel: >> >> echo "12.45-" | sed -e 's/[$-]/[^-]/g' >> > echo "12.45-" | sed -e 's/\([^-]*\)-$/-\1/' Ist vermutlich irrelevant, aber was ist, wenn zwischendrin auch ein - vorkommen kann? 63
> test=`nmap localhost` > echo "$test" > > Die Anfuehrungszeichen beim "echo" sind wichtig, sonst sind die > Zeilenumbrueche weg. Genau das war mein Fehler! Vielen lieben Dank! Ich hab mich dumm und dämlich gesucht: Manchmal sieht man halt den Wald vor lauter Bäumen nicht! 64
Das ist Bürokratengerede, fgrep ist de facto portabler als »grep -F«. »Obsolescent« heißt in POSIX.2/SUSv2 nur soviel wie »wir wollen das nicht mehr in unserem sauberen Standardtext sehen«. Die praktische Umsetzung fällt an diesen Stellen regelmäßig anders aus. 65
Ich möchte (mit GNU sed version 3.02) den Ausdruck ".z" durch nichts ersetzen, wenn er an einem Zeilenende vorkommt. (Es geht darum, den Inhalt eines afio-Archivs mit dem Listing, was angeblich archiviert wurde, zu vergleichen.) In der manpage steht dazu: POSIX.2 BREs should be supported, but they aren t completely yet. The \n sequence in a regular expression matches the newline character. There are also some GNU extensions. Das klappt aber nicht: head monday.verbose |grep .z$ |sed -e 's/QPW.z\n/QPW/g' liefert einfach wieder var/export/forschung/Laborliste/Chemikalienliste.QPW.z var/export/forschung/Laborliste/Chemikalienliste.doc.z usw. Das selbe, wenn ich die '' weglasse und \\n schreibe. Nun ja, für mein aktuelles Problem kann ich es interaktiv machen: 66
Kann ich ein (bash-)Skript so schreiben, dass es sich beim Aufruf automatisch in den Hintergrund verzieht? Mit "normalen" Programmen geht das ja, und das "&" anzuhängen geht zwar, ist aber halt lästiger, als wenn es das Sript alleine könnte. 67
> >Kann mir jemand ein Kommando sagen, mit dem ich alle Zeilen mit genau > >3 Woertern aus einer Datei ausgeben kann? > > awk 'NF == 3 {print}' 68
| > wie kann ich mit egrep sagen, dass er nur in der ersten Zeile oder | > nur bis zum n.ten Simikolon einer Datei suchen soll. Er meint IMHO nicht in der ersten Zeile bis zum ersten Semikolon (Oder irgendeiner Zeile bis zum Semikolon.) sondern sowas wie: 34534;3454235;345342;;;2354 1234231;342543;;235443;354 sdfwdf:sf;sdfsd;sdf;sdf Wenn er jetzt bis zum, z.B., 3ten semikolon suchen will bekommt er bei obigem Beispiel 34534;3454235;345342; als Lösung. 69
>>> Nicht-rekursive Ausgabe aller dot-Dateien und dot-Verzeichnisse in $HOME: >>> dots=".[`echo \\\\001--0-\\\\0177`]*"; ls -d ~/$dots >> (Zuallermindest) Shell-spezifisch. > Das \xxx koennte ein Problem werden, falls die Shell das nicht kann. > Ansonsten sollten Shells des Type Bourne-Shell es koennen. (· Generell kennt Bourne sh(1) keine Tilde-Expansion. · Auf den meisten Systemen wird \xxx direkt akzeptiert. Auf Free- und NetBSD ist bei der sh(1) (eher eine ash), jedoch ein »-e« notwendig. (Hier kennt echo(1) selbst das \xxx übrigens gar nicht, statt dessen ist printf(1) zu verwenden. ksh88/93, pdksh(1) und zsh(1) verstehen \xxx, bash(1) verlangt hingegen ein »-e« (wie auch GNU echo(1). (BTW: Für ksh88 gilt übrigens noch, daß sie sich bzgl. »-n« nach dem jeweiligen echo(1) richtet. Auf SunBSD verhält sich die Bourne sh(1) angeblich gemäß demjenigen echo(1), das zuerst im Pfad steht (/usr/bin vs /usr/5bin, letzteres kennt \xxx). Das stimmt aber nicht, das built-in kennt \xxx gar nicht. »echo« ist überhaupt nicht portabel (ganz zu schweigen von anderen Escape- Sequenzen und Optionen, wie »\a«, »\c«, »-n« etc.). printf(1) ist deutlich besser, aber auf einigen Systemen wiederum nicht vorhanden. · In bash-1/2 ist (neben »-e«) noch '\177' statt '\0177' nötig.
AUTOR: sven.mascheck@student.uni-ulm.de 70
> aus einer Art configure-Skript heraus möchte ich feststellen, ob auf dem > System eine ksh existiert und wenn ja, um welche Version es sich > handelt. Das erste ist ja kein Problem, indem ich nacheinander die > Existenz von ksh93, ksh88, ksh teste (für weitere Möglichkeiten bin ich > ganz Ohr). Aber wie finde ich bei erfolgreicher Suche die Versionsnummer > heraus, ohne eine interaktive Shell zu starten und Control-V > einzutippen? Eine Option »--version« o.ä. gibt es leider nicht. 71
> warum funktioniert ogendes nicht ? > sed -e 's/\n/ /g' »\n« ist der Zeilenseparator, also zunächst mal kein Bestandteil der Zeile. Wenn Du z.B. zwei aufeinanderfolgende Zeilen zu einer Zeile machen willst, musst Du diese erst verbinden und dann das (nun erreichbare) Newline-Zeichen löschen: sed 'N;s/\n//' 72
> In welcher Manpage oder sonstigen Doku ist eigentlich beschrieben, wie > man Steuerzeichen in Regular Expressions einsetzt, z.B. in sed? In termio(7I) und vi(1). > Konkret geht es mir darum, dass ich in einer Datei (vermutlich stammt > sie von einem Mac) gerne die ^M durch newline ersetzen würde. Wenn die Datei derzeit gar keine Newlines enthält, ist sie keine Textdatei im Unix-Sinn und kann per definitionem nicht mit sed oder vi bearbeitet werden. tr ist tatsächlich das geeignetste Werkzeug: tr '<Strg+V><Strg+M>' '<Newline>' 73
> > Eine > > vernünftige regexp-Manpage habe ich zwar nicht, aber hier > > Schon mal 'man sed' bis zum Ende durchgelesen? > > Unter "SEE ALSO" steht u.a. ed(1) und regex(5). Die 5 ist > zumindest auf meinem cygwin-system falsch, es muss 3 und/oder 7 > sein. Also einfach mal 'man ed' und 'man 3 regex' und > 'man 7 regex' eingeben. Ach, Mift. Ich hatte nicht daran gedacht, dass es mehrere geben könnte (und man 3 regex hilft hier natürlich nicht weiter). 74
>gibt es eine Möglichkeit aus einem Offset (von date +%s) das Datum zu >berechnen ohne daß man sich diese Funktion selber schreiben muß? >...oder hat bereits jemand ein shell-script (bash) mit dieser Funktion >geschrieben? Du könntest (falls vorhanden) GNU AWK dafür verwenden. $ timestamp=1000000000 $ gawk 'BEGIN{print strftime("%a %b %d %H:%M:%S %Z %Y",'$timestamp')}' Sun Sep 09 03:46:40 CEST 2001 $ gawk 'BEGIN{print strftime("%Y-%m-%d %H:%M:%S",'$timestamp')}' 2001-09-09 03:46:40 75
> Die Quelle des neuen Verhaltens ist die beigelegte readline 4.2a. > Linkt man bash 2.05a gegen eine alte readline 4.2, dann tritt das > nicht auf. Aha. Wenigstens haben wir jetzt den Schuldigen. > Allerdings ist diese Änderung weder dokumentiert, noch finde ich eine > Möglichkeit sie abzuschalten. Ich habe auch nichts dergleichen finden können. Die Option, die für das Anhängen des Slashes verantwortlich ist, heißt "mark-directories" und ist bei mir auf "on" gesetzt. Ich schreib mal einen Bug-Report... 76
> kann man irgendwie (Gnu BASH) Standarderror durch eine Pipe "pipen", > sodaß es danach wieder auf STDERR rauskommt? > [...] Allerdings muss ich dazu STDERR auf STDOUT umleiten (2>&1). > "Schöner" wäre wohl eine Lösung, die STDOUT unberührt lässt, STDERR liest, > durch grep pipe´d und wieder nach STDERR ausgibt. Im Prinzip so: (exec 3>&1; (echo FOO >&2; echo bar) 2>&1 >&3 | tr '[A-Z]' '[a-z]' >&2) | tr '[a-z]' '[A-Z]' 77
> ich will mit fuehrender null zaehlen, also von 001 bis 100 i=1 while [ $i -lt 101 ] do if [ $i -lt 10 ] then ii=00$i elif [ $i -lt 100 ] then ii=0$i else ii=$i fi echo $ii i=$(($i+1)) done TOM - der "seq -w 1 100" leider nicht finden kann 78
> i=1 > while [ $i -lt 101 ] > do > printf "%.3i\n" $i > done > > und printf gibts hier sowohl auf linux als auch auf solaris. Leider ist es auf letzterem ein externes Kommando, so daß es in einer Schleife unmäßig Ressourcen verbraucht. Nimm awk: awk </dev/null 'BEGIN { for (i = 1; i <= 100; i++) printf("%03d\n", i) }' 79
>ist es möglich, mit einfachsten Mitteln, am liebsten also nur mit einem >bash-Befehl, eine Zeile in einer Textdatei zu löschen? Ohne es getestet zu haben: ziel=23 # welche Zeile soll weggelassen werden? i=1 while read x; do test $i -ne $ziel && echo $x i=`expr $i + 1` done <eingabedatei >ausgabedatei Ich wuerde das im realen Leben aber nie in Shell machen: warum unnoetig Rechenzeit verbraten? 80
ich versuche seit geraumer Zeit Zahlen aus einer Zeichenkette herauszulesen, die durch ; getrennt sind ( also z.B. 123;456;8;9 ). Das müsste doch ganz einfach unter awk mit der Funktion split(string, awkArray, ";") gehen!? Doch wie komme ich an das awkArray heran? ich benutze die ksh und versuche folgendes: awk '{split($searchString, awkArray, ";");}' searchString="123;456;789;" echo ${awkArray[0]} 81
> Ich habe da ein Skript, in dem der vollständige Output eines Befehls, > sowohl stderr als auch stdout, in ein Logfile geschrieben sowie an einen > User gemailt wird. Ich möchte dort stderr auch ungern verlieren, > allerdings würde ich ihn gerne auch noch in system log schreiben. Um das Prinzip zu verdeutlichen: mkfifo -m 600 /tmp/fifo$$ sed 's/.*/syslog: &/' </tmp/fifo$$ & (exec 5>&1; (echo foo >&2; echo bar) 2>&1 >&5 | tee /tmp/fifo$$ >&2) 2>&1 | tee /dev/tty | tr '[a-z]' '[A-Z]' rm /tmp/fifo$$ sed entspricht logger, /dev/tty dem zusätzlichen Logfile, und tr entspricht mail. »>&2) 2>&1« kannst Du Dir im konkreten Fall sparen. 82
> echo -e "g/^\/proc/d\nwq\n" | ed test Auch das ist proprietärer Müll, korrekt lautet es echo 'g/^\/proc/d w' | ed test 83
> kann mir mal einer den Unterschied zwischen den 2 folgenden Befehlen > erklaeren? > > 1. "find . -name 'message' &> info.txt" > > 2. "find . -name 'message' > info.txt 2>&1" Ja. Die erste ist proprietärer Müll und die zweite die standardisierte, überall lauffähige Form. 84
>> Existiert eine Möglichkeit unter der bash das datum zwei Tage hochzuzählen >> mit dem Befehl date. Harald haette dazusagen muessen: "Mit unix tools geht das nicht so einfach, aber mit GNU date kann man das so schreiben:" >date --date= "2 days" Denn unter Unix: $ date --date= '2 days' date: illegal option -- - date: illegal option -- d date: invalid argument -- te=2 days usage: date [-u] mmddHHMM[[cc]yy][.SS] date [-u] [+format] date -a [-]sss[.fff] >Das steht auch in 'info date' unter 'Examples'. $ info date ksh: info: not found GNUs not everything. 85
> case $VAR in > *[^0-9]*) Das ist bash-spezifischer Code. Vertretbar portabel ist »[!0-9]«, das wurde schon in System III undokumentiert unterstützt und über die SVID nach POSIX.2 übernommen. Probleme gibt es nur mit der aus v7 stammenden Shell uralter BSD-Systeme und einzelnen fehlerhaften Versionen der bash 1 (letzteres IIRC). 86
> while : > do .... > > [...] > TEMPVAR="dummy" > [...] > done | sort | uniq >> $TMP_OUT_FILE > > echo $TEMPVAR > > Die Variable TEMPVAR ist immer leer solange nach dem done der PIPE sort > PIPE uniq steht, warum ? Wie dem auch sei, die Schleife läuft in einer Subshell, weil sie Teil einer Pipe ist. D.h. der in der Subshell zugewiesene Wert für TEMPVAR ist lokal nur in der Subshell bekannt und wird nicht an die aufrufende Shell "exportiert". Syntaktisch blöd und potentielle Quelle für manch einen subtilen Fehler. Das "Syntaktisch blöd" war nicht auf dein Skript bezogen sondern auf die Tatsache, dass die Zuweisung von Variablen innerhalb einer Schleife (bzw. ihr anschließender Wert außerhalb derselben) davon abhängig ist, ob die Schleife Teil einer Pipe ist. Dies ist eine Eigenart der Shell-Syntax, die leider das Verständnis eines Programms mitunter nicht unbedingt fördert. Man muss das mit den Subshells einfach lernen und akzeptieren, wie es ist. NB: Richtig fies sind scheinbar triviale Konstrukte wie echo a | read x Probier s mal anhand von _verschiedenen_ Shells aus... 87
ich finde für eine (wahrscheinlich ziemlich einfache) Frage keine Antwort. Gegeben folgendes Miniaturscript: #!/bin/sh exec 1>>$log exec 2>>$error ... Sehr praktisch weil alle Meldungen fein säuberlich getrennt mitgeloggt werden. Aber wie schaltet ich das jetzt wieder ab oder umgehe es für einen Befehl? Meine Scriptanleitungen schweigen sich diesbezüglich leider aus und google konnte ich auch nichts entlocken. 88
Kann mir jemand sagen, wie ich Dateien auf Grösse und Datum/Zeit vergleichen kann, ich möchte nämlich auf meinem Fileserver eine art bereinigungssystem erstellen, aber ich kenne keinen Befehl, der mir diese ermöglicht > man find > man test Hmpf, ich hasse das, klar kenne ich die mans, wenn ich dort wüsste, wie ich die dateilängen und das/die Datum/Zeit herausfinden kann, würde ich nicht hier posten 89
> wie kann ich testen, ob in einem Verzeichnis Dateien enthalten sind? Je nachdem, ob »test -e« auf den Zielsystemen vorausgesetzt werden kann: 90
> Ist > tr '[[:upper:]]' '[[:lower:]]' > GNU-spezifisch oder portabel? Immerhin portabel im Sinne von IEEE 1003.1-2001 91
> gibt es eigentlich eine shell die nicht nur globbing sondern auch wahlweise > regular expressions zulässt? > Bash kennt ja "extglob", aber das ist wieder eine ganz neue Syntax ich hätte > schon gerne die aus sed bekannte Syntax und würde dazu auch von bash auf was > anderes umsteigen. Vielleicht psh: Description: interactive shell with the power of perl 92
> Einerseits wird "$" bei den Zeichen aufgeführt, die zwingend gequotet > werden müssen, wenn sie als literales Zeichen verwendet werden sollen, > andererseits wird aus den Abschnitten zur Token-Recognition und den > verschiedenen von "$" eingeleiteten Expansionen nicht wirklich klar, daß > "$" in anderem Kontext als zur Einleitung einer Expansion verboten ist, > bzw. "$" immer ein Metazeichen ist (was sich auch damit deckt, daß "$" > am Ende eines Wortes immer literal gilt). > > Stehe ich hier nur gerade irgendwo auf dem Schlauch, oder wird das > tatsächlich von SUSv2 nicht weiter spezifiziert? »If an unquoted "$" is followed by a character that is either not numeric, the name of one of the special parameters (see Special Parameters ), a valid first character of a variable name, a left curly brace ({) or a left parenthesis, the result is unspecified« (unter »Word Expansions« und ebenso in ISO/IEC 9945-2:1993(E), 3.6, p. 125). Vor einem »"« oder »'« "behalten Bourne-Shell, ash, ksh88 und pdksh ein »$« bei, von bash und ksh93 wird es entfernt. Letztere erlauben auch die Verwendung lokalisierter Variablennamen in Abhängigkeit von LC_CTYPE, was eine spektakulär dämliche Idee ist. 93
> Leider erwaehnst Du nicht, welche Shell Du benutzt. Die gaengigen > Shells verwenden aber zum Test einer Bedingung eckige Klammern bzw. > das Programm "test". >> if (( 0 == 0 )) > if [ 0 == 0 ] if [ 0 = 0 ] »==« ist an dieser Stelle eine der tollen »Innovationen« von David Korn und dem Bash-Team, die Code ohne jede Not zu normalen Shells inkompatibel machen. Eine niederträchtige Taktik, die der Microsofts nicht unähnlich ist. 94
> kann mir jemand folgende Zeilen erklären? > > # Determine the base and follow a runlevel link name. > base=${0##*/} > link=${base#*[SK][0-9][0-9]} 95
[pattern matching] > In welcher Manpage kann ich darüber etwas finden? man ksh, page 13ff >> ksh habe ich auf Linux nicht installiert, andere Shells müssen das also >> auch unterstützen, oder nicht? Ist das nicht schon in der Bourne Shell >> enthalten? > > Ich habe es inzwischen in der Man page der bash gefunden. Welche Shells > können denn diese Pattern überhaupt? Die sh(1) von Solaris kann: ${parameter:-word} If parameter is set and is non-null, substitute its value; otherwise substitute word. ${parameter:=word} If parameter is not set or is null set it to word; the value of the parameter is substituted. Positional parameters may not be assigned in this way. ${parameter:?word} If parameter is set and is non-null, substitute its value; otherwise, print word and exit from the shell. If word is omitted, the message "parameter null or not set" is printed. ${parameter:+word} If parameter is set and is non-null, substitute word; otherwise substitute nothing. Die bourne-shell (unter SunOS) kann das ## also nicht. Die ksh unter SunOS kann zusaetzlich: ${parameter%word} Remove Smallest Suffix Pattern. The word will be expanded to produce a pattern. The parameter expansion then will result in parameter, with the smallest por- tion of the suffix matched by the pattern deleted. ${parameter%%word} Remove Largest Suffix Pattern. The word will be expanded to produce a pattern. The parameter expansion then will result in parameter, with the largest por- tion of the suffix matched by the pattern deleted. ${parameter#word} Remove Smallest Prefix Pattern. The word will be expanded to produce a pattern. The parameter expansion then will result in parameter, with the smallest por- tion of the prefix matched by the pattern deleted. ${parameter##word} Remove Largest Prefix Pattern. The word will be expanded to produce a pattern. The parameter expansion then will result in parameter, with the largest por- tion of the prefix matched by the pattern deleted. Die GNU bash kann zusaetzlich noch ${parameter:offset} ${parameter:offset:length} ${#parameter} ${parameter/pattern/string} ${parameter//pattern/string} Die zsh kann die / und // der bash sowie zusaetzlich ${+name} ${^spec} ${#spec} ${=spec} ${~spec} ${name:#pattern} ${name::=word} Die pdksh zusaetzlich zur ksh noch: ${#name[*]}, ${#name[@]} The number of elements in the array name. 96
> Diese Lösung mit done <Datei erzeugt ja *keinen* CHILD mehr... Doch, in einer Bourne-Shell, wie ich hier vor nicht einmal einer Woche (!) in <3C978988.QQ11UH50@bigfoot.de> gesagt habe. Dort findet sich auch ein Hinweis, wie man das portabel umgehen kann. In einer echten Korn-Shell (nicht pdksh) hingegen läuft auch das letzte Glied einer Pipe nicht in einem Childprozeß. 97
>Durch "echo" Einträge zwischendurch kann ich sagen, dass die einzelnen >Zeiten ($diff) meist richtig kalkuliert werden, jedoch treten >zwischendurch immer wieder Fehlermeldungen 'onlinezeit: let: s=08: >value too great for base (error token is "08")' (immer nur error >token is "08" und "09" ... unterschiedlich bezogen auf h, m oder s) bash interpretiert (beim rechnen) jede Zahl, die mit 0 anfängt als Oktalzahl und da es dort nur die Ziffern 0-7 gibt, ist 08 keine gültige Zahl. Lösung: 10#08 bzw: let tmp_up=$((10#$h*3600+10#$m*60+10#$s)) 98
>auf Debian habe ich mit der Bash folgendes Problem: >case "hallo" in *[A-Z]*) echo ja ;; esac >gibt mir "ja" aus. Offensichtlich ist die bash dort auf >case-insensitive eingestellt. Wie kann ich das ändern? >(etwas seltsam ist, daß es in der Kommandozeile richtig >funktioniert, jedoch nicht, wenn ich es in einem Skript laufen >lasse.) >kann man das irgendwie für ein Skript anpassen? Die Wunder der Internationalisierung. Ein LC_COLLATE=C sollte helfen (sofern LC_ALL nicht gesetzt ist). 99
Ich möchte in einer Shellfunktion eine Variable in Abhängigkeit vom beim Aufruf mitgegebenen Argument verwenden. Das heisst, ich suche eine Definition Message () {irgendwas;} so dass Message 1 zum Kommando command $variable1 wird und Message 2 zu command $variable2 Und da blicke ich nicht mehr durch. Etwas konkreter schaut das so aus: ... Ich habe dann experimentiert mit 100
Wie belegt man am einfachsten eine Variable mit einem Text, der in einer Datei steht? Spricht irgendwas gegen variable="`cat file`" oder gibt es etwas noch viel einfacheres? Zeilenumbrüche etc sind egal, da die Variable sowieso an dialog verfüttert wird; \n sollte erhalten bleiben. 101
Hallo Frank, und ich habe noch einen: auf dem SuSE system steht in der manpage von awk: /[[:alnum:]]/ zu verwenden und es funktioniert: awk -F'::' '{ OFS="::" ; if ( $11 ~ /[[:alnum:]]/ ) print $0}' file auf Debian jedoch bekomme ich nicht heraus, ebensowenig eine Fehlermeldung. Für mein Programm mit schwerwiegenden Folgen. Kurz herumgespielt und herausgefunden: awk -F'::' '{ OFS="::" ; if ( $11 ~ /[:alnum:]/ ) print $0}' file funktioniert auf Debian, nicht jedoch auf SuSE. Gott, ist das eine Katastrophe. Meine Lösung jetzt: awk -F'::' '{ OFS="::" ; if ( $11 ~ /[A-Za-z0-9]/ ) print $0}' file Könnte mir bitte jemand sagen, ob ich damit jetzt auf der sicheren Seite bin, oder mich noch weitere Überraschungen erwarten werden? Es gibt da mawk und gawk, beide jedoch conform zu POSIX 1003.2. Warum klappt das dann nicht? > awk -F'::' '{ OFS="::" ; if ( $11 ~ /[A-Za-z0-9]/ ) print $0}' file Schreib noch ein LC_ALL=C davor (oder LC_COLLATE=C, je nach Umgebung). > Könnte mir bitte jemand sagen, ob ich damit jetzt auf der sicheren > Seite bin, oder mich noch weitere Überraschungen erwarten werden? Bei LC_COLLATE=C ist die basic collation sequence systemübergreifend festgeschrieben und entspricht dem US-ASCII-Zeichensatz. Wenn Du Umlaute dazunehmen willst, mußt Du allerdings LC_CTYPE entsprechend setzen. > Es gibt da mawk und gawk, beide jedoch conform zu POSIX 1003.2. In Details halt nicht. In Details ist sowieso fast jede Software nicht POSIX.2-compliant, für die das behauptet wird. > Warum klappt das dann nicht? Weil mawk eben keine character class expressions implementiert. Das dürfte daran liegen, daß das C-Interface zu den internationalisierten RE-Features in POSIX.2 braindamaged ist. So gibt es zwar locale- spezifische character classes, aber nur ein Widechar-Interface, um darauf zuzugreifen (iswctype()/wctype()). Das ist allerdings auf vielen Systemen gar nicht vorhanden. Auf die basic collation sequence kann man ohne Zugriff auf libc-Interna überhaupt nicht zugreifen. Man kann nicht mal feststellen, ob eine Zeichenkette überhaupt ein collating symbol ist (außer, indem man die eigene RE-Implementation mit regcomp() mischt, was extrem ekelhaft wäre). Daraus ergibt sich, daß es unmöglich ist, POSIX.2-REs für andere Locales als C portabel zu implementieren (Implementationen, die das Gegenteil zu belegen scheinen, sind im Detail stets fehlerhaft). Da man internationalisierte REs in der C-Locale aber gar nicht braucht, kann man es gleich ganz lassen. >> Das macht doch wenig Sinn, wenn ich nur [A-N] haben will. > > Dann ist diese Lösung natürlich nicht ausreichend, sie bezog > sich aber auch nicht auf [A-N] Ich machte mir generell Gedanken, was mir logisch und unlogisch erscheint, vielleicht auch in der Hoffnung, daß die Kritik mal an den richtigen gerät. > Du kannst halt nicht beides gleichzeitig haben: > Die volle Unterstützung sprach-/landesspezifischer > Regelungen und die Nichteinhaltung dieser Regeln > in einzelnen - dir genehmen - Fällen. Oh langsam bitte, es geht nicht darum etwas zu gestalten, was nur mir genehm ist. Ich motze hier mal laut herum, was mir so als Anfänger immer wieder Kopfschmerzen bereitet und was mir nicht gefällt. Diskonformität zwischen den verschiedenen shells und dann noch verschiedenen OS bzw. Distributionen bereitet in der Praxis doch nur Unmut und ich glaube nicht nur Anfängern wie mir. Es verhindert auch, daß sich mehr Liebhaber dafür finden werden. > Wenn eine Sprachnorm nun mal "AaBb..." sortiert > (oder "AÄaäBb..."), dann hat es halt Vor- und Nachteile, > wenn man sich daran hält. Der Nachteil ist, wenn es jedesmal und überall anders ist. > Wenn du darauf verzichten kannst, setz "LC_COLLATE" oder > "LC_ALL" entsprechend (evtl. nur lokal). Es wird meiner Ansicht nach nur unnötig komplex. 102
>macht es Sinn/bringt es Vorteile, statt >if [ -z "$VAR" ] ; then >das Konstrukt >if [ "X$VAR" = "X" ] ; then >zu benutzen? >(und dann gibt es ja noch [ ! "$VAR" ]). Eventuell schon. Hier z.B. mit ksh Version M-11/16/88i unter Solaris 8: $ VAR="=" $ [ -z "$VAR" ] && echo empty ksh: test: argument expected $ [ "X$VAR" = "X" ] && echo empty $ [ -n "$VAR" ] && echo not empty ksh: test: argument expected $ [ "X$VAR" != "X" ] && echo not empty not empty 103
>> Das ist so wie es dasteht flacsh. Die ksh fuehrt in der login-shell per >> Default nur .profile aus (wenn man mal von /etc/profile absieht). >> In einer "nicht-login" ksh wird aber (falls die Environment-Variable >> "ENV" gesetzt ist und auf eine lesbare Datei zeigt) diese Datei in der >> aktuellen shell ausgefuehrt (gilt wie schon geschrieben nicht fuer >> login-shells). > Falsch, es gilt auch für Login-Shells. Die bash führt ihre .bashrc > allerdings nicht in Login-Shells aus. Gut, dann korrigiere ich dahingehend, dass es vereinzelt ksh-Versionen gibt, die $ENV nicht in login-shells ausfuehren (ich habe mal gewaltig geflucht, weil mir eine solche Variante untergekommen ist und ich nicht sofort die Ursache gefunden hatte, das war IIRC damals unter AIX3.2.4). 104
theoretisch würde mein Skript wie folgt aussehen, nur dass so Konflikte mit den Anführungsstrichen auftreten: find . -type f -exec sh -c ' ^ file=${0##*/} name=`echo "$file" | awk '{ s=$$1; print s }'` ^ ^ echo "$name" ' {} \; ^ (Das Beispiel ist auf das wesentliche Prinzip beschränkt.) Die awk-Anweisungen möchte ich aber auf jeden Fall *nicht* als separates Skript auslagern, sondern wie oben angegeben verwenden. In doppelte Anführungsstriche kann ich aber die awk-Anweisungen nicht einschließen, das funktioniert nicht, und so wie oben angegeben gibt es Konflikte zwischen den "Shell-Anführungsstrichen" und den "awk-Anführungsstrichen". Wie kann ich dieses Problem lösen? 105
Dass man für obige Skripte eine "moderne" »awk«-Version benötigt (z.B. eine, die zur SUSv2 konform ist), hatte ich bereits an anderer Stelle erwähnt. Gleiches gilt wegen »read -r« auch für die Shell, auf älteren Bourne-Shells (bei Verwendung von »read« ohne »-r«) sollte mal also auch noch sicherstellen, dass die Datei-/Pfadnamen keine Backslashes enthalten. Das macht man analog zu Zeilenumbrüchen ebenfalls mit »find«. 106
>>> ps wux | grep -q [p]pp-off || exit 0 >>> [...] Manchmal (aber nicht immer) wird bemaengelt: >>> 4955 Done | grep -q [p]pp-off >>> /ppp-wart: line 13: 4960 Broken pipe ps wux >>> [...] Die Shell ist "GNU bash version 2.0.2", >> bash-FAQ, Abschnitt E2. > Danke - schau ich mir am Vormittag mal an. >> grep -q liest die Eingabe in vielen Implementationen nach dem >> ersten Treffer nicht mehr weiter. > Das sollte eigentlich hier keine Rolle spielen Das spielt hier sogar die entscheidende Rolle. Wenn grep sich vorzeitig beendet - wohin soll ps dann noch seinen seinen Output schicken? 107
Subject: Nur erste Zeile bei grep auslesen? wenn ich einen grep starte und dieser liefert mir als ergebnis z. B.: Text1;Hallo Text2;Hallo wie kann ich jetz davon nur die erste zeile herausfiltern. Ausgangsgrep: grep "^Text" test.txt 108
Thema: Doppelt sortieren. Henning Hülsebusch wrote: > 0003 01.01.2002 irgendwelche > 0008 31.04.2001 anderen > 0002 03.03.2002 Zeilen > 0001 28.02.2001 stehen noch > 0007 31.04.2001 hier > > Sortiert werden soll in zwei Schritten, zu erst dem Datum nach, und dann > vorne der laufenden Nummer nach (jeweils aufsteigend). Herauskommen soll > also: > > 0001 28.02.2001 stehen noch > 0007 31.04.2001 hier > 0008 31.04.2001 anderen > 0003 01.01.2002 irgendwelche > 0002 28.02.2002 Zeilen > > Habe schon diverse Versuche mit "sort" gestartet, aber bisher ohne Erfolg. > Jemand eine Idee ? Danke Mit »awk« die Felder umstellen, dann mit »sort« sortieren, und ursprüngliche Reihenfolge der Felder mit »awk« wiederherstellen. 109
Subject: schnelles ln -s Ich muss hier (mehrmals) Dateien, die in Unterverzeichnissen sind, über eine flache Hierarchie (= 1 Verzeichnis) zugreifbar machen. Dazu mache ich | for i in $(find . -type f); do ln -s $i .; done oder | find . -type f|xargs ln -s --target-directory . Beide Varianten sind _extrem_ langsam, letzteres läuft hier seit 6 Stunden und hat gerade mal ca. 350,000 Dateien verlinkt (Linux, ext3). Welche schnellere Möglichkeit gibt es, diese Links anzulegen? 110
Subject: Re: shell programmierfrage \ Michael Mauch wrote: > > $ cat blub > > #!/bin/sh > > > > i=foo > > while read line > > do > > i=$line > > echo $i > > done << ! > > bar > > ! > > echo $i > > > > $ ./blub > > bar > > foo > > $ > > Ups. Die einzige mir zugängliche Shell, die dieses Verhalten zeigt, ist > die Original-Bourne-Shell auf Tru64 (wenn BIN_SH nicht auf xpg4 oder svr4 > gesetzt ist). Die /bin/sh auf FreeBSD und NetBSD, bash, pdksh, zsh und > ash auf Linux geben alle zweimal "bar" aus - genau wie die /bin/sh auf > Tru64, falls BIN_SH auf xpg4 oder svr4 gesetzt ist. Ich bekomme bei allen gerade greifbaren Shells ebenfalls zweimal 'bar', mut Ausnahme der /bin/sh auf Solaris, also analog zu deiner Beobachtung. > Woran liegt das jetzt? Wenn man das Here-Doc weglässt und das "bar" > manuell eingibt, gibt auch die /bin/sh von Tru64 (ohne BIN_SH) zweimal > "bar" aus: > > #!/bin/sh > > i=foo > while read line > do > i=$line > done > echo $i Weil die »while«-Schleife nicht in einer Subshell abgearbeitet wird, da sie nicht Bestandteil einer Pipe ist. Damit ist die Variable 'i' innerhalb der Schleife gleich der Variable 'i' außerhalb. Wenn du die Schleife zum Bestandteil einer Pipe machst, dann wird sie je nach Shell in einer Subshell abgearbeitet oder auch nicht: i=foo echo bar | while read line do i=$line echo $i done echo $i Subshell bedeutet jedoch, dass das Setzen von 'i' innerhalb der Schleife keinen Einfluss auf das davon völlig unabhängige 'i' außerhalb derselben hat. Das resultiert dann in bar/foo bei einer /bin/sh auf Solaris, ash, bash und pdksh; dagegen bar/bar bei ksh88i, ksh93 und zsh. Also auf höchst subtile Weise unportables Verhalten, und darauf bezog sich denn wohl auch Jürgens Beispiel. Interessant finde ich das hier von ksh88/93 abweichende Verhalten der pdksh. Alle Klarheiten beseitigt? 111
Subject: Re: Datei zeilenweise lesen * Arne wrote: > > das sieht schon ganz gut aus. Mein Problem ist jetzt noch, daß in der > Ausgangsdatei die Zeilen irgendwie eingerückt sind. Wenn ich die > Zeilen mit echo wieder ausgebe, wird das erste Zeichen einer Zeile > ganz nach links geschoben. Der Rest der Zeile sieht dann wieder normal > aus, auch mit den Abständen. IFS setzen: while IFS= read -r zeile Weitere Infos dazu liefert Dir 'man sh' oder 'man bash', dort meinetwegen auch 'help read'. 112
Subject: Re: Wie bekomme ich ein \n weg * Knut Rauscher wrote: > > ich möchte hier in einer Textdatei, in der letzten Zeile > das \n löschen. Was mir z.B. der od -canzeigt: > ... > Wie bekomme ich das letzte \n weg? Mit sed habe ich es nicht hinbekommen. awk 'ORS=""; { if (N) { print "\n"; } print $0; N=1; }' 113
Subject: Re: mit großen Zahlen Rechnen Hans Anthes wrote: > Irgendwo in einem Script steh so eine Zeile "echo $[$zahl1+$zahl2]" soweit > ist das ja kein Problem, aber Zahl1 als auch Zahl2 werden so richtig groß > (zb so groß 2910865710) und da kommt eben nicht das richtige Ergeniss > raus. Wie kann ich denn dafür sorgen das so ein Shell Script da den > passenden Type für verwendet (sofern das überhaupt geht ?) Ich würde bc benutzen wenn es verfügbar ist: karsten@tecneeq:~> echo $((2910865710+2910865710)) 1526764124 karsten@tecneeq:~> echo "2910865710+2910865710" | bc 5821731420 114
Subject: Re: Nullzeichen in Parametern Hauke Laging <hauke.laging@tim.tu-berlin.de> wrote: > bekommt man irgendwie Nullzeichen (und anderes Zeug, das man nur über > Escape-Sequenzen generieren kann) in Variablen rein? NULs nicht, sonst alles. Was spricht dagegen, daß Du das einfach ausprobierst? Was für Escape-Sequenzen überhaupt? 115
Subject: Re: gueltigkeitsbereich von Variablen Nikolaus Filuswrote: > ich habe gerade ein ähnliches Problem, nur daß ich die Eingabe aus einem > Programm auslese. Wie kann ich dort die Variablen ausserhalb der while > Schleife verwenden? > > logprint | while read name value msg; do > .... > done > # print last line a 2nd time > echo $name $value $msg Beginn und Ende der Subshell mit Klammern festlegen und den Wert innerhalb der Schleife noch einmal zuweisen, da den Variablen von read bei EOF leere Strings zugewiesen werden; etwa so: echo foo | (while read xline do line=$xline done echo $line) Ralf Wildenhues wrote: > Naja, und die subshell-Antwort sieht zwar vermutlich einprägsamer aus, > dürfte aber doch im Allgemeinen teurer als die exec-Lösung (die im > thread erwähnt wird) sein, oder nicht? exec funktioniert nicht, wenn der Input aus einer Pipe stammt, und das Anlegen einer FIFO ist noch aufwendiger. Außerdem wird die Subshell außer von echten kshs ja sowieso erzeugt. 116
Subject: Direktes und indirektes Piping Date: Mon, 16 Sep 2002 22:16:38 +0200 Newsgroups: de.comp.os.unix.shell Die Shell-Aufrufe saxon -w0 tbtmplte.xml /usr/local/lib/tbook/tbtoltx.xsl > junk tbrplent < junk funtionieren, saxon -w0 tbtmplte.xml /usr/local/lib/tbook/tbtoltx.xsl | tbrplent hingegen nicht. tbrplent bricht mitten in der Prozessierung ab. Worin unterscheiden sich denn beide Varianten, vom Filter tbrplent aus gesehen? 117
Subject: Re: Logfile auswerten mit awk, wenn Inhalt in Spalten wechselt > while read LINE ; do ^^^^ Falscher Namespace benutzt, siehe SUSv[23], Base Definitions, «Environment Variables». Typischer PC-DOS-Umsteiger-Fehler. > PROTO=$(echo $LINE | tr " " "\n" |\ > grep -E "^msg=|^proto=|^rcvd=|^send=" | sed 's/^msg=.*/proto=vpn/' | > args ) > echo "$PROTO" > done < MyLogFile Ah, wie sagenhaft performant, mindestens vier Prozesse pro Zeile eines Logfiles! Der OP hat nicht ohne Grund geschrieben, daß er awk dafür nehmen wollte. echo '...' | sed ' :loop s/"\([^ "]*\)"/\1/ s/\("[^"]*\) \([^"]*"\)/\1_\2/ t loop' | awk '{ proto = "VPN" send = 0 rcvd = 0 for (i = 1; i <= NF; i++) { if ($i ~ /^send=/) send = substr($i, 6) else if ($i ~ /^rcvd=/) rcvd = substr($i, 6) else if ($i ~ /^proto=/) proto = substr($i, 7) } send_total[proto] += send rcvd_total[proto] += rcvd } END { for (proto in send_total) printf("proto=%s send=%d rcvd=%d\n", proto, \ send_total[proto], rcvd_total[proto]) }' 118
Subject: Re: Rückgabe ähnlich in C > Daher sollte es nicht allzu überraschend sein, dass Du > auch eine eigene Funktion so aufrufen kannst: > > ERGEBNIS=$(addiere 4 5) Eine wirklich exzellente Methode, Performance und Portabilität gleichermaßen sinnlos zum Fenster hinauszuwerfen, und auch noch so hübsch im falschen Namespace. Bravo! 119
Subject: Re: bestimmte dateien (*) aus ls ausschließen > > ls !(datei2) > > > > (ksh, bash) > > hier unter Mandrake-8.2, funktioniert das nicht. Lies das bash-Manual, da steht drin, welche Option du aktivieren musst. Besser jedoch vermeidest du diesen unportablen Schnickschnack und verwendest eine portable Lösung mit »grep«. 120
Subject: Re: ${par:-word} > > NB: Ist das hier die Manual-Vorlesestunde oder was? ;-) > > Sorry das ich das nicht aus der man bash ersehen kann. Dein Fehler ist, dass du dich auf das bash-Manual verlässt. Es gibt nämlich bessere Manuals, wo genau das (richtig) drin steht, was im Zusammenhang mit portabler Shell-Programmierung relevant ist. Diesen ganzen bash/ksh/zsh-Schnickschnack, welcher u.U. (z.B. bei interaktiven Shells) "ganz nett" sein kann, will man in Shell-Skripten i.d.R. jedenfalls vermeiden. Diese Erweiterungen sind in der Dokumentation jedoch meist von den portablen Eigenschaften nicht unterscheidbar, was die Doku nicht gerade brauchbarer macht. Sieh' dir SUSv2 oder -3 an. 121
Subject: Re: gueltigkeitsbereich von Variablen > Naja, und die subshell-Antwort sieht zwar vermutlich einprägsamer aus, > dürfte aber doch im Allgemeinen teurer als die exec-Lösung (die im > thread erwähnt wird) sein, oder nicht? exec funktioniert nicht, wenn der Input aus einer Pipe stammt, und das Anlegen einer FIFO ist noch aufwendiger. Außerdem wird die Subshell außer von echten kshs ja sowieso erzeugt. 122
Subject: Re: [BASH] "Globale" Variablen > NO=0 > /bin/cat test.txt | while read line > do > NO=1 > echo $NO > done > echo $NO > > Beim letzten echo nach der Schleife wird 0 ausgegeben. Wieso? Wie bekomme > ich an dieser Stelle eine 1, die in der Schleife gesetzt wird? Und schon wieder ein "useless use of cat award"-Kandidat. Und schon wieder einer, der auf den "while Schleife wird in subshell ausgeführt" hereinfällt. Es gibt keine "globalen Variablen" bei shells. Höchstens solche, die exportiert werden, also im Environment von Kindprozessen auftauchen, und solche, die es nicht tun. Und "Environment" wird nicht an Elternprozesse kommuniziert. -------------------------------------- > Ich schreibe ein kleines Skript für die Bash (Start vereinfacht): > > #!/bin/bash > NO=0 > /bin/cat test.txt | while read line > do > NO=1 > echo $NO > done > > echo $NO Die "while"-Schleife wird in einer Sub-Shell ausgeführt, weil die Eingabe von einer Pipeline gelesen wird. Portabel funktioniert das folgende Beispiel: exec 3<&0 0<test.txt # file descriptor 0 als Nr. 3 merken, 0 umleiten while read line do ..... done exec 0<&3 3<&- # fd 0 wiederherstellen, fd 3 schliessen -------------------------------------- >> Und wieso [keine Subshell] bei: >> >> while read Variable >> [...] >> done < Datei > > Weil hier keine zwei Prozesse gleichzeitig ausgefuehrt werden [...] In der traditionellen Bourne Shell erzeugt eine Umlenkung von "while", und z.B. auch von "{ list;}", sehr wohl eine Subshell. >> Ich meine sogar, dass das mal anders war? > > Nein. "Es ist noch so." AUTOR: sven.mascheck@student.uni-ulm.de 123
On Wed, Oct 01, 2003 at 05:37:51PM +0200, Manfred Lotz wrote: > dd if=infile ofile=extract.dat ibs=1 skip=791 obs=64k count=11665408 > > > Allerdings ist das Lesen mit ibs=1 ziemlich ineffektiv. > > Gibt es eine Möglichkeit, dies effektiver zu gestalten? Ich würde gerne ab > dem extrahieren mit grosser Blocksize arbeiten. ja. Nimm ibs=7 skip=113. Ansonsten: selberschreiben. 10-20 zeilen Code in C oder perl. 124