[fli4l] Nur #!/bin/sh oder auch #!/bin/bash?

Christoph Schulz fli4l at kristov.de
Di Jan 31 14:00:08 CET 2017


Hallo!

K.  Dreier schrieb:

> Da es
> nun doch scheinbar ein paar Unterschiede gibt (z.B. "``" für sh vs "()"
> für bash)

Das ist ein Irrglaube. Beides funktioniert wunderbar mit sh, bash und auch 
der ash auf dem fli4l (siehe unten). Die $(...)-Schreibweise hat allerdings 
den Vorteil, dass man sich nicht um das Entwerten von `-Anführungsstrichen 
kümmern muss, will heißen,

# für die Fakultäts-Funktion siehe unten!
echo $(seq $(factorial 1) $(factorial 2))

ist einfacher zu schreiben als:

echo `seq \`factorial 1\` \`factorial 2\``

> Kurzum: kann ich auf fli4l (4.0-testing) in Skripten #!/bin/bash
> nutzen?

Ja und nein.

Syntaktisch kannst du _nicht_ "#!/bin/bash" in dein Skript schreiben, weil 
es diesen Interpreter auf dem fli4l einfach nicht gibt.

Aber auf dem fli4l läuft die "ash", und diese unterstützt viele wichtige 
(aber nicht alle) bash-Funktionen. Diese Shell ist unter /bin/sh zu finden, 
so dass du in deine Skripte auf dem fli4l einfach

#!/bin/sh

in die erste Zeile schreiben und die erweiterten Funktionen der ash nutzen 
kannst.

Allerdings ist mir keine Auflistung o.ä. bekannt, die zusammenfasst, welche 
Funktionen der bash in der ash funktionieren und welche nicht. Ich fasse mal 
einige Dinge zusammen, die mir direkt einfallen und auf dem fli4l 
funktionieren:


### Variablen ###
# Wert von A
fence 4.0.0-r47062 # A="abc"
fence 4.0.0-r47062 # echo $A
abc
fence 4.0.0-r47062 # echo ${A}
abc
# ":-" : Wert von A, aber Alternative "x" falls leer oder undefiniert
fence 4.0.0-r47062 # unset A
fence 4.0.0-r47062 # echo ${A:-x}
x
fence 4.0.0-r47062 # A=""
fence 4.0.0-r47062 # echo ${A:-x}
x
# ":+" : Leere Zeichenkette, falls A leer oder undefiniert,
# aber Alternative "x" sonst (d.h. Ersetzung von A falls A nicht leer)
fence 4.0.0-r47062 # unset A
fence 4.0.0-r47062 # echo ${A:+y}

fence 4.0.0-r47062 # A=""
fence 4.0.0-r47062 # echo ${A:+y}

fence 4.0.0-r47062 # A="x"
fence 4.0.0-r47062 # echo ${A:+y}
y
# "+" : Leere Zeichenkette, falls A undefiniert, aber Alternative "x" sonst
# (d.h. Ersetzung von A falls A definiert und nicht leer)
fence 4.0.0-r47062 # unset A
fence 4.0.0-r47062 # echo ${A+y}

fence 4.0.0-r47062 # A=""
fence 4.0.0-r47062 # echo ${A+y}
y
fence 4.0.0-r47062 # A="x"
fence 4.0.0-r47062 # echo ${A+y}
y
# ":?" : Wert von A, falls A nicht leer, aber Fehlermeldung "y" sonst
fence 4.0.0-r47062 # unset A
fence 4.0.0-r47062 # echo ${A:?y}
-sh: A: y
fence 4.0.0-r47062 # A=""
fence 4.0.0-r47062 # echo ${A:?y}
-sh: A: y
fence 4.0.0-r47062 # A="x"
fence 4.0.0-r47062 # echo ${A:?y}
x
# "?" : Wert von A, falls A definiert, aber Fehlermeldung "y" sonst
fence 4.0.0-r47062 # unset A
fence 4.0.0-r47062 # echo ${A?y}
-sh: A: y
fence 4.0.0-r47062 # A=""
fence 4.0.0-r47062 # echo ${A?y}

fence 4.0.0-r47062 # A="x"
fence 4.0.0-r47062 # echo ${A?y}
x
# ":=" : Variableninhalt ersetzen, falls leer oder undefiniert
fence 4.0.0-r47062 # unset A
fence 4.0.0-r47062 # echo ${A}

fence 4.0.0-r47062 # echo ${A:=x}
x
fence 4.0.0-r47062 # echo ${A}
x

### Zeichenketten ###
fence 4.0.0-r47062 # A="abcdefabcdef"

## Teilzeichenketten ##
# Präfix abschneiden
fence 4.0.0-r47062 # echo ${A#abc}
defabcdef
fence 4.0.0-r47062 # echo ${A#*d}
efabcdef
fence 4.0.0-r47062 # echo ${A##*d}
ef
# Suffix abschneiden
fence 4.0.0-r47062 # echo ${A%def}
abcdefabc
fence 4.0.0-r47062 # echo ${A%c*}
abcdefab
fence 4.0.0-r47062 # echo ${A%%c*}
ab
# Teilwort extrahieren
fence 4.0.0-r47062 # echo ${A:2}
cdefabcdef
fence 4.0.0-r47062 # echo ${A:2:3}
cde

## Suchen und Ersetzen ##
# Erstes Vorkommen ersetzen
fence 4.0.0-r47062 # echo ${A/b/x}
axcdefabcdef
# Alle Vorkommen ersetzen
fence 4.0.0-r47062 # echo ${A//b/x}
axcdefaxcdef

### Rechnen ###
fence 4.0.0-r47062 # B=10
# Ausdrücke mit Variablen
fence 4.0.0-r47062 # echo $((5*B+7))
57
# Ausdrücke mit Variablen, die Ausdrücke (mit Variablen) beinhalten
fence 4.0.0-r47062 # C=B+2
fence 4.0.0-r47062 # echo $C
B+2
fence 4.0.0-r47062 # echo $((C))
12
fence 4.0.0-r47062 # echo $((5*C+7))
67

### Funktionen ###
# Fakultät mit Iteration (Schleife) und lokalen Variablen
fence 4.0.0-r47062 # function factorial() {
  local result=1 i=$1
  while [ $i -ne 0 ]; do
    result=$((result * i))
    i=$((i - 1))
  done
  echo $result
}
fence 4.0.0-r47062 # factorial 0
1
fence 4.0.0-r47062 # factorial 5
120

# Fakultät mit Iteration (seq) und lokalen Variablen
fence 4.0.0-r47062 # function factorial() {
  local result=1 i
  for i in $(seq 1 $1); do # hier könnte `seq ...` statt $(seq ...) stehen!
    result=$((result * i))
  done
  echo $result
}
fence 4.0.0-r47062 # factorial 0
1
fence 4.0.0-r47062 # factorial 5
120

# Fakultät mit Rekursion (ganz ohne Variablen)
fence 4.0.0-r47062 # function factorial() {
  if [ $1 -eq 0 ]; then
    echo 1
  else
    echo $(($1 * $(factorial $(($1 - 1)))))
  fi
}
fence 4.0.0-r47062 # factorial 0
1
fence 4.0.0-r47062 # factorial 5
120


Was die ash definitiv nicht unterstützt, sind die folgenden Konstrukte

- [[ ... ]]             (Auswertung bedingter Ausdrücke;
                         nur außerhalb der Shell, keine Operatoren wie =~)
- (( ... ))             (spezielle Auswertung numerischer Ausdrücke)
- <( ... ), >( ...)     (Prozess-Ersetzung)
- A=(1 2); echo ${A[1]} (Arrays)
- ${A^...}, ${A,...}    (Änderung der Groß-/Kleinschreibung)


Viele Grüße,
-- 
Christoph Schulz
[fli4l-Team]


Mehr Informationen über die Mailingliste Fli4L