Kann jemand erklären, was dies in einem Shell-Skript bedeutet?
while read -r line
do
if [ "${line#*'Caused By'}" != "$line" ]; then
echo "Yes"
fi
done
Kann jemand erklären, was dies in einem Shell-Skript bedeutet?
while read -r line
do
if [ "${line#*'Caused By'}" != "$line" ]; then
echo "Yes"
fi
done
Antworten:
${line#*'Caused By'}
ist eine bestimmte Instanz der Variablensubstitution ${parameter#word}
(wie im bash
Handbuch und auch im POSIX-Standard für die sh
Shell beschrieben).
In ${parameter#word}
wird das Muster word
vom Anfang des Wertes von entfernt $parameter
. Es heißt „entfernen Kleinste Präfix - Muster“ genannt , weil es den Entfernen kürzesten passende Präfix - String nach dem Muster in word
(mit ##
anstelle von #
dem entfernt längsten passenden Präfix - String).
In diesem speziellen Beispiel wird die Zeichenfolge Caused by
(und alles, was davor liegt, dank der *
), falls vorhanden, aus dem Wert von entfernt $line
. Die einfachen Anführungszeichen um die Zeichenfolge sind redundant.
Durch Vergleichen des Ersetzungsergebnisses mit dem Wert der Variablen selbst ermittelt der Test, ob der Wert von $line
den Text enthält Caused by
, und druckt, Yes
falls dies der Fall ist.
Dies hat den gleichen Effekt wie
if [[ "$line" == *'Caused by'* ]]; then
echo 'Yes'
fi
in bash
, ksh93
oder zsh
, oder
case "$line" in
*'Caused by'*) echo 'Yes'
esac
in jeder sh
Schale.
Die Schleife in der Frage liest "Zeilen" von der Standardeingabe. Eine Diskussion hierzu finden Sie in der Frage " IFS = read -r line " verstehen .
Die linke Seite der if-Bedingung verwendet die Pattern Matching- Funktionalität von bash. Die übereinstimmende Zeichenfolge wird entfernt, wenn sie die 'Verursacht von' enthält. Die Zeile ist nicht mehr identisch mit der vorherigen und löst daher nicht die if-Klausel aus.
Hier ist ein Beispiel, das Sie auf der Shell ausführen können:
echo -e "Number 1 Caused by me.\nNumber 2 is normal.\n" |
while read line; do
echo "${line#*'Caused by'}"
done
Ergebnis:
me.
Number 2 is normal.
Aktion (oder Ausführung in diesem Fall) spricht immer lauter. Schauen wir uns also an, was dieses Skript bei der Ausführung tut (entschuldigen Sie die Freiheit, die Ausgabe ausführlicher zu gestalten):
while read -r line
do
if [ "${line#*'Caused by'}" != "$line" ]; then
echo "Line contains string Caused by"
else
echo "Line does not contain string Caused by"
fi
done
Input: String with Caused by
Output: Line contains string Caused by
Input: Just a normal string
Output: Line does not contain string Caused by
Der in diesem Skript verwendete Mustervergleich "${line#*'Caused by'}
ersetzt alle Zeichenfolgen (aufgrund des Platzhalters *
) vom Anfang bis zum Ende von Caused by in der eingegebenen Zeile und vergleicht sie dann mit dem ursprünglichen $line
Parameter, um festzustellen, ob sie gleich sind oder nicht. Einfach ausgedrückt, alles, was es tut, ist eine Überprüfung, ob die Zeile die Zeichenfolge Caused by enthält . Schließlich wird gedruckt. Zeile enthält Zeichenfolge Verursacht durch, wenn die Zeile Verursacht durch enthält .
Nun ein paar Worte zur Shell-Parametererweiterung für das ${parameter#word}
Format mit einigen Beispielen:
Wenn das Muster mit dem Anfang des Parameterwerts übereinstimmt, ist das Ergebnis der Erweiterung der erweiterte Parameterwert mit dem kürzesten Übereinstimmungsmuster (Fall "#") oder dem längsten Übereinstimmungsmuster (Fall "##") ) gelöscht.
$ test=aabbcc
$ echo ${test#*bb}
$ cc
$ test=aabbcc
$ echo ${test#a*b}
$ bcc
Ein Beispiel für das am längsten übereinstimmende Musterformat:
$ test=aabbcc
$ echo ${test##a*b}
$ cc
Referenz: man bash
:${parameter#word}