Kornshell

from Wikipedia, the free encyclopedia

The Korn shell (proper spelling Korn shell , also known as ksh, ksh86, ksh88and ksh93referred to) is a standard developed by David Korn command line interpreter as well as the description of the scripting language, which is implemented by this interpreter. Originally written for UNIX , there are now implementations not only for UNIX-like systems , but also for Windows and AmigaOS .

The language description itself is in the public domain , but not every implementation. The original source of the ksh93since 2000 (or 2005, see story also in the public domain).

The KornShell (in the version from 1988) formed the basis for the POSIX Shell specification and meets the POSIX2 standard. It is fully backwards compatible with the Bourne Shell ( sh) and takes over many of the innovations of the C Shell ( csh).

history

The KornShell - the spelling coined by its author - was developed by David Korn at the Bell Labs of AT&T in the early 1980s and presented at the USENIX conference on July 14, 1983. It was originally based on a forms interpreter that David Korn had worked on. Whose syntax was based on the Bourne Shell : designed differed from that but by significant improvements JobControl one of the, C Shell modeled Command History and Command aliasing .

ksh86

The new shell quickly became popular with AT & T's employees, so that it quickly became the de facto standard shell there . As more and more developers who left the company asked for availability outside of AT&T, the shell was eventually released for a fee as part of the UNIX System Toolchest . This ksh86was one of the first versions published in this way and served, among other things, as a model for the shell of earlier versions of QNX .

ksh88

The successor version ksh88quickly became a success and is still being supplied by many providers of Unix systems today: HP-UX, for example, has its own version as the default shell, and AIX (version 4 and higher) is supplied with an original ksh88as the default shell. At the end of the 1980s, the ksh88 specification was established, which formed the basis for the description of the command interpreter in the POSIX standard and is essentially identical to it. ksh88AT&T and Novell hold the rights to the .

ksh93

In 1993 the shell and its scripting language were fundamentally revised. This new specification (or implementations that follow it) is known as ksh93 . Individual versions are identified by appended letters, for example the current version is ksh93u +, which followed the version ksh93u, ksh93t + and their predecessor ksh93t .

Until 2000, Korn Shell was proprietary software, the rights were held by AT&T and Lucent Technologies . In 2000 the source code was finally published, first under AT & T's own version of a public domain license, from version ksh93q (2005) under the Common Public License .

KornShell and its environment

Differences to and similarities with other shells

Command line editing, file name completion

One of the most important changes compared to its predecessor, the Bourne Shell , was the ability to repeat the entered command line or to change it before executing it again. This function was taken over from the C Shell Bill Joys , but significantly expanded compared to this; in kshwere from the beginning three editing modes available, all mimicked the behavior of popular editors: vi , Emacs and XEmacs .

Another new feature was the ability to automatically complete file names or to display a list of all files matching an incomplete file name while entering the command.

In ksh93addition to the File Name Completion , the Command Completion , i.e. the completion of incompletely specified, executable files, was introduced. This function is identical to that of the bash.

Treatment of pipelines

In contrast to the bash, pipelines in the are kshnot automatically executed in subshells. This has serious consequences for the scope of variables:

#! /usr/bin/ksh

typeset -i linenum=0
typeset  line=""
cat /path/to/input | while read line ; do
     (( linenum += 1 ))
done
echo $linenum

exit 0

In bashwould 0output the last line because the while..doneloop is executed as part of a pipeline in a subshell and is $linenumtherefore only incremented in this subshell. In a KornShell, however, the number of lines in the file is output. However, many replicas (for example pdksh) do not realize this behavior, but behave like in this regard bash.

FPATH-Variable

Since its first versions, the kshhas had system variables FPATHthat define a standard search path for files that contain shell functions, analogous to the variables PATHfor executable files. This enables function libraries to be set up that behave similarly to shared libraries . This is a big advantage compared to other shells, in particular bash, which has to parse out all the functions to be used when the script is started.

Floating point support

In ksh93addition to the usual integer arithmetic, the also has the floating point data type and the associated methods for processing such data.

Coprocess facility

A unique among the popular shells feature is the ability of both ksh88as well as ksh93background processes asynchronously work off and still be managed with messages - the so-called coPROcess Facility . A process is processed asynchronously in the background, but remains connected to the parent process via two data channels (executed as file descriptors 4 and 5) and can be controlled via this bidirectional channel.

variants

Not least because of the originally licensed situation, various implementations of the Korn shell have been written over the course of time, which were or are more or less compatible with the original shell.

dtksh

dtksh( Desktop ksh ) is a version of the ksh93for programming graphical interfaces under X11 . This version extends the original script language with connections to the Common Desktop Environment or Motif , X, Xt and tcl .

pdksh/ mksh/oksh

pdkshis a public domain implementation of the Korn Shell, which, however, has little compatibility in some points ( e.g. pipelines are executed in subshells like bash and in contrast to all kshversions). Most of the features of the ksh88and a few of the are ksh93supported. In addition, it brings some of its own extensions.

mkshis a pdkshderivative that emphasizes ease of use and lean but correct code. Improvements to projects like Debian and OpenBSD are also incorporated . In contrast to OpenBSD-ksh is mkshportable and is available for different platforms. The program also contains many enhancements and detailed improvements (for example unlimited arrays or ~/.mkshrcsupport), but deliberately dispenses with functionalities that bloat the code, such as a bash-like $ PS1 syntax; nor is it intended as a substitute for /bin/sh. mkshis maintained by the MirOS project.

okshis a Linux port of the OpenBSD variant of the Korn Shell, whereby only as many changes as necessary are entered in the OpenBSD code in order to make it compilable under Linux. This variant is used as the standard shell /bin/shunder DeLi Linux .

Ports to AmigaOS and Microsoft Windows

SKshis a version for AmigaOS that offers a number of Amiga -specific features such as ARexx -interoperability.

The MKS Korn Shell is another commercial Korn Shell implementation. It is part of Microsoft's Windows Services for UNIX (SFU) and the subsystem for UNIX-based applications (SUA) of the Windows Vista Enterprise and Ultimate Editions. It was drastically determined at a USENIX conference that it has significant flaws in compatibility. The anecdote surrounding it (reproduced here in the words of David Korn) went down in history:

“It was at a USENIX Windows NT conference and Microsoft was presenting their future directions for NT. One of their speakers said that they would release a UNIX integration package for NT that would contain the Korn Shell.

I knew that Microsoft had licensed a number of tools from MKS so I came to the microphone to tell the speaker that this was not the "real" Korn Shell and that MKS was not even compatible with ksh88. I had no intention of embarrassing him and thought that he would explain the compromises that Microsoft had to make in choosing MKS Korn Shell. Instead, he insisted that I was wrong and that Microsoft had indeed chosen a "real" Korn Shell. After a couple of exchanges, I shut up and let him dig himself in deeper. Finally someone in the audience stood up and told him what almost everyone in the audience knew that I had written the 'real' Korn Shell. I think that this is symbolic about the way the company works. "

“It happened at a USENIX Windows NT conference and Microsoft presented the further development that NT should take. One of their spokespersons said they were going to release a UNIX integration package and it would include a KornShell.

I knew Microsoft had bought licenses for some tools from MKS, so I came to the microphone and explained to the speaker that this wasn't a “real” KornShell and that MKS wasn't even compatible with the ksh88. I had no intention of exposing him, and I expected him to explain the compromise Microsoft had made in choosing the MKS Korn Shell. Instead, he insisted that I was wrong and that Microsoft, of course, was using a “real” KornShell. After some back and forth, I fell silent and left it to him to ride himself deeper and deeper. Finally someone in the audience got up and told him what almost everyone in the audience knew by now: namely, that I had written the real KornShell. I think that's an example of how this company works. "

- David Korn Tells All

Introduction to the KornShell scripting language

From the beginning, KornShell was ksh93intended primarily as a script interpreter and only secondarily as an interactive shell. The following introduction deals with the differences between ksh88and ksh93only marginally, but tries to work out the peculiarities of the KornShell programming language.

Comments

KornShell only knows one form of comment: from the pound sign everything up to the end of the line is considered a comment, which corresponds to that //in C ++ . There are no cross-line comments.

A special form of comment is the shebang , which defines the executing program, but this is a kernel function . To the shell, this is a comment like any other. If the hash mark is to be used as a literal, it must be enclosed in quotation marks or escaped (its special function removed by a preceding backslash character '\').

#! /usr/bin/ksh

# Dies ist ein Kommentar
print - "Hello World."     # Kommentar: führe print-Statement aus
print - "#"          # Doppelkreuz in Anführungszeichen wird als Zeichen interpretiert
print - \#           # escapetes Doppelkreuz

exit 0

Positional and named variables, here documents

In the KornShell, as in the Bourne Shell, variables are addressed by a dollar sign ('$') and an identifier enclosed in curly brackets (the curly brackets can be left out in some cases). However, only the identifier is used for the assignment.

#! /usr/bin/ksh

typeset variable="Hello World."      # Zuweisung
print - ${variable}            # Verwendung der Variablen
print - $variable             # Verwendung, alternative Form

exit 0

Named variables correspond to what is called variables in other high-level languages : an identifier that references a memory location in which a value can be stored. In contrast to other high-level languages, KornShell does not require any formal declaration and neither does it require any explicit typing . Nevertheless, a declaration including the data type can - and should (!), For the sake of readability and documentation - be made using the keyword typeset , especially if it differs from the string . The following data types are available:

  • String
  • Integer
  • Float (only ksh93)
  • Compound (only ksh93)
  • Array

In addition, any variable, regardless of type, can be used as a string. What distinguishes these variables is that they have names, which is why they are called named variables .

There are also unnamed, so-called positional variables , which are automatically filled in the case of scripts with the transferred command line parameters, in the case of shell functions with the transferred arguments. They are with numerals ( ${0}, ${1}, ${2}etc.), which ${0}always contains the name of the program or function.

With the exception of $0, positional variables can be processed with the keyword shift . shiftdeletes the content of the variable $1and then $1assigns the value of $2, $2with the value of $3.. with the value of : $n-1$n

#! /usr/bin/ksh

print - "Name des Scripts............: ${0}"
print - "Erstes übergebenes Argument : ${1}"
print - "Zweites übergebenes Argument: $2"   # alternativ auch ohne Klammern
print - "Drittes übergebenes Argument: $3"

shift
print - "Erstes übergebenes Argument : $1 (war vorher $2)"
print - "Zweites übergebenes Argument: $2 (war vorher $3)"
print - "Drittes übergebenes Argument: $3 (war vorher $4)"

exit 0

In connection with a loop, an unknown number of parameters transferred during program creation can be processed piece by piece.

A special feature that can only be found in some shell languages ​​is the here document . It is a string filled with a fixed text, which is not declared like a variable, but only once, e.g. B. is used as input of a command. However, variables can be used within a here document , which are replaced by their content when the script is executed.

#! /usr/bin/ksh

typeset chMsg="Hello World."

mail [email protected] <<EOF
Hallo recipient,
der Text der Nachricht lautet: $chMsg
EOF

exit 0

Everything between the delimiters EOF(the delimiters are freely selectable identifiers) is sent as input to the command mailand $chMsgis replaced by the value of the variable assigned above. In other high-level languages ​​the here documents correspond most closely to string literals; in C ++, for example, raw string literals .

Loops, branches

Loops and branches are compatible with those of the Bourne Shell from which they are obtained. The Korn shell provides three types of loops are available: for, whileand until.

The behavior of the forloop corresponds to that of other programming languages: a list of values ​​is iteratively assigned to a loop variable and one pass through the loop body is carried out with this value.

for Variable in <Liste von Werten>
do
  Liste von Kommandos
done

In contrast to most languages, however, no number values ​​(integers) are iterated, but strings that are taken from a fixed list. However, this fixed list can also contain wildcards :

#! /usr/bin/ksh
typeset chLoopVar=""

# ---------------------------- Schleife mit Festwerten
for chLoopVar in a b c d e ; do
  print - "Der Wert der Variablen chLoopVar ist: $chLoopVar"
done

# ---------------------------- Schleife mit Files
print - "Eine Liste von txt-Dateien:"
for chLoopVar in *txt ; do
  print - "   -> $chLoopVar"
done

exit 0

The while- and the untilloop are both syntactically the same as also logically equivalent, with the difference that the untilloop is executed until a certain condition is met , the whileloop on the other hand, as long as a certain condition is met . The following statements on the whileloop therefore also apply accordingly to the untilloop.

The whileloop works a little differently than it is used to in other languages, because KornShell originally did not have its own method for comparisons and therefore used the external command test. In the meantime, KornShell has a built-in function that corresponds to this command, but the syntax of the loop has not changed. whileexecutes the loop body as long as a specified command returns error level 0 (corresponds to TRUE).

while Kommando ; do
    Liste von Kommandos
done

until Kommando ; do
    Liste von Kommandos
done

As the following example shows, in the KornShell whileloops replace the loops used in other languages for. The second example shows the flexibility gained by using the external command. The shell-internal command readis used in connection with a pipeline to process a data stream line by line:

#! /usr/bin/ksh
typeset -i iLoopVar=0
typeset  chLine=""

# ------------------------------- while-Schleife als for-Schleifen-Ersatz
while [ $iLoopVar -le 10 ] ; do
    print - "Wert von iLoopVar: $iLoopVar"
    (( iLoopVar += 1 ))           # inkrementiere iLoopVar
done

# ------------------------------- listet alle Kommandos mit 3 Buchstaben in /usr/bin
find /usr/bin -name "???" -print | while read chLine ; do
    print - "Kommando: $chLine"
done

exit 0

The KornShell knows two types of branching: if..fiand case..esac.

ifused as well as whilean external program to generate the required logical value. ifmay optionally by means of the keywords elif also process multiple conditions, also optionally be executed is when not applying all previous conditions elsebranch.

if Kommando ; then
  Liste von Kommandos
elif Kommando ; then
  Liste von Kommandos
elif Kommando ; then
  Liste von Kommandos
...
else
  Liste von Kommandos
fi

In the case of usual comparisons, testits built-in counterpart is used for this, but any program can also be executed and an action can be started, depending on its return value:

#! /usr/bin/ksh

typeset -i iIn=0

# ------------------------------- einfaches if
if [ 1 -eq 1 ] ; then
  print - "1 ist tatsächlich gleich 1"
fi

# ------------------------------- if-else
if /path/to/program -opt arg1 arg2 ; then
  print - "Programm program wurde ohne Fehler beendet."
else
  print - "Programm program lieferte einen Fehler zurück."
fi

# ------------------------------- mehrstufiges if
print - "Geben Sie eine Ziffer (0-3) ein:" ; read iIn
if [ $iIn -eq 0 ] ; then
  print - "Sie haben 0 eingegeben."
elif [ $iIn -eq 1 ] ; then
  print - "Sie haben 1 eingegeben."
elif [ $iIn -eq 2 ] ; then
  print - "Sie haben 2 eingegeben."
elif [ $iIn -eq 3 ] ; then
  print - "Sie haben 3 eingegeben."
else
  print - "Sie haben was anderes eingegeben."
fi

exit 0

caseevaluates a single expression through variable expansion and executes one of them from several alternative code blocks depending on its value (this can be a Shell Regular Expression , also known as a File Glob ). This corresponds approximately to that of Pascal known case .. ofor the switch()from C .

case Ausdruck in
  Wert)
    Kommando
    ...
  ;;

  Wert)
    Kommando
    ...
  ;;
  ...
esac

The example above, executed with caseinstead of if, would read:

#! /usr/bin/ksh
typeset -i iIn=0

print - "Geben Sie eine Ziffer (0-3) ein:" ; read iIn
case $iIn in
  0)
    print - "Sie haben 0 eingegeben."
    ;;

  [123])                      # 1, 2 oder 3 als Regexp
    print - "Sie haben 1, 2 oder 3 eingegeben."
  ;;

  *)                        # default-Ast
    print - "Sie haben etwas anderes eingegeben."
  ;;
esac

exit 0

Functions

As in all other procedural programming languages , KornShell also offers the option of logically self-contained and / or often recurring code parts in subroutines - called functions here . The syntax is identical to that of the Bourne Shell or the POSIX Shell, the KornShell understands both variants:

function Funktionsname   # Bourne Shell-artig
{
     Kommando
     Kommando
     ...
}

Funktionsname ()      # POSIX-Shell-artig
{
     Kommando
     Kommando
     ...
}

In contrast to other programming languages, the input or output is regularly used to receive inputs from other program parts or to transmit results to other program parts (pipelining). In this respect, functions in the shell behave similarly to external programs.

Function arguments are - analogous to command line parameters - transferred using positional variables . The keyword return (optionally followed by an integer with the value 0- 255) can be used to jump back to the calling program and a function result that can be queried and treated by it as an error level . Every function should therefore contain at least one such returncommand (at the end).

#! /usr/bin/ksh

function pShowText
{
  print - "Dies ist ein Beispieltext."
  print - "Bei Ausführung der Funktion pShowText()"
  print - "wird er auf <stdout> ausgegeben."
  return 0
}

function pShowAnyText
{
  typeset iCnt=0
  while [ "$1" != "" ] ; do
    print - "$1"
    (( iCnt += 1 ))
    shift
  done
  return $iCnt
}

# --------- Hauptprogramm
typeset iRetVal=0

print - "Hier wird pShowText() aufgerufen:"
pShowText
print - "das Ergebnis kann auch in einer Pipeline verarbeitet werden:"
pShowText | grep 'ei'    # zeigt alle Zeilen, in denen "ei" vorkommt, also die ersten beiden

print - "pShowAnyText() gibt alle übergebenen Argumente zeilenweise aus:"
pShowAnyText "erste Zeile" "zweite Zeile" "dritte Zeile"
iRetVal=$?          # sichert den Rückgabewert von pShowAnyText()
print - "Es wurden $iRetVal Argumente an pShowAnyText() übergeben."

exit 0

Variable expansion or parameter substitution

An essential difference between shell languages ​​and conventional programming languages ​​is the handling of variables : in a normal high-level language, a variable is ultimately a memory location in which a value can be stored and which can be addressed by a name. In der ksh(as well as der bashand similar languages) a variable is also a place for storing values, but the only direct operation is the assignment. All other ways of addressing the variable are more or less complex functions that receive the content of the variable as an argument, process it and output the result of this processing. The content of the variable itself remains unchanged.

The simplest of these functions is $<Bezeichner>or ${<Bezeichner>}, which reproduces the content of the variable unchanged. On the other hand, it roughly indicates ${#<Bezeichner>}the length of the (string) variables <Bezeichner>and thus corresponds to the C function strlen().

The interpreter first evaluates these variable expressions in command lines in the course of command line parsing and replaces them with their result before the resulting actual command line is evaluated. The following overview shows some options for transforming the variable content:

${<Bezeichner>}, $<Bezeichner>
Content of the variable <Bezeichner>without change
${#<Bezeichner>}
Length of the variable <Bezeichner>
${<Bezeichner>:-<Wert>}
If the variable is <Bezeichner>declared and its content is not equal to zero (or the empty string), this content is output, otherwise the one specified in the second part of the expression.
${<Bezeichner>:=<Wert>}
Like ${<Bezeichner>:-<Wert>}, but instead <Bezeichner>assign the resulting value to the variable . It equals
<Bezeichner>="${<Bezeichner>:-<Wert>}"
This is usually used to supply variables with default values. With this and all similar expansions, the expressions following the identifier are only evaluated if necessary. Invalid expressions can thus remain undetected for a long time, which is one of the risks (to be avoided through appropriate tests) in larger shell script projects.
${<Bezeichner>#<regexp>}, ${<Bezeichner>##<regexp>}
If the specified matches <regexp>the beginning of the content of the variable Bezeichner, then this content minus the part that matched is output, otherwise the entire content. In this way, parts of the content of a variable can be cut off. In the variant with #, the smallest matching part is cut off, in ##the longest. For example, the expression ${<PathName>##*/}from the path name cuts everything down to the last /, which roughly basenamecorresponds to the command .
${<Bezeichner>%<regexp>}, ${<Bezeichner>%%<regexp>}
Similar to ${<Bezeichner>#<regexp>}or ${<Bezeichner>##<regexp>}, only that the part to be cut off is not matched from the beginning but from the end of the variable content. The command dirnamecan be ${<Bezeichner>%/*}emulated by expansion , for example.
#! /usr/bin/ksh
typeset chVar="hello world"

print - "Inhalt der Variablen chVar: $chVar"
print - "Länge der Variablen chVar.: ${#chVar}"
print - "Defaultwert...............: ${chVar:-foo} hingegen: ${notdeclared:-foo}"

chVar="/path/to/some/file"
print - "Pattern entfernen..........: ${chVar##*/} bzw.: ${chVar%/*}"

exit 0

literature

  • Morris I. Bolsky, David A. Korn: The KornShell command and programming language . Prentice Hall, Englewood Cliffs, NJ 1989, ISBN 0-13-516972-0 .
  • Morris I. Bolsky, David A. Korn: The new KornShell command and programming language . Prentice Hall PTR, Upper Saddle River, NJ 1995, ISBN 0-13-182700-6 .
  • Barry Rosenberg: KornShell Programming Tutorial . Addison-Wesley Professional, Boston, MA 1991, ISBN 0-201-56324-X .
  • Barry Rosenberg: Hands-On KornShell93 Programming . Addison-Wesley Professional, Boston, MA 1998, ISBN 0-201-31018-X .

Web links

Individual evidence

  1. ^ The Open Group Base Specifications; 2. Shell Command Language. Retrieved May 23, 2013 .
  2. ^ Website of the KornShell project. Retrieved June 19, 2013 .
  3. ^ David Korn: KSH - A Shell Programming Language. USENIX Conference Proceedings, Toronto, Ont. Summer 1983, pp. 191-202.
  4. Sven Maschek: Some ksh versions available. February 18, 2012, accessed February 10, 2016 .
  5. QNX Manual: see. Retrieved February 10, 2016 .
  6. AIX v6.1 Infocenter. Retrieved May 24, 2013 .
  7. Andreas Siegert: AIX Survival Guide . 1st edition. Addison-Wesley Professional, Boston 1996, ISBN 0-201-59388-2 .
  8. Package Notes and Changes (changelog of ksh93). Retrieved May 23, 2013 .
  9. David Korn Tells All (Question 5, "True Story?"). Retrieved May 24, 2013 .
  10. David Korn Tells All (Question 1, "Comparison"). Retrieved June 8, 2013 .