it-swarm.com.de

Suche nach Teilzeichenfolgen ohne Berücksichtigung der Groß- und Kleinschreibung in einem Shell-Skript

Wie kann ich ein Shell-Skript schreiben, das eine Teilstring-Übereinstimmung der Befehlsausgabe ohne Berücksichtigung der Groß- und Kleinschreibung durchführt?

22
Miguel Roque

Hier ist zunächst ein einfaches Beispielskript, das Groß- und Kleinschreibung nicht ignoriert:

#!/bin/bash
if [ $(echo hello) == hello ]; then
    echo it works
fi

Versuchen Sie, den String Hallo auf der rechten Seite zu ändern, und er sollte nicht mehr it works Echo. Versuchen Sie, echo hello Durch einen Befehl Ihrer Wahl zu ersetzen. Wenn Sie Groß- und Kleinschreibung ignorieren möchten und keine der Zeichenfolgen einen Zeilenumbruch enthält, können Sie grep verwenden:

#!/bin/bash
if echo Hello | grep -iqF hello; then
    echo it works
fi

Der Schlüssel hier ist, dass Sie eine Befehlsausgabe an grep weiterleiten. Die Anweisung if testet den Exit-Status des Befehls ganz rechts in einer Pipeline - in diesem Fall grep. Grep wird nur dann mit Erfolg beendet, wenn es eine Übereinstimmung findet.

Die Option -i Von grep sagt, dass Groß- und Kleinschreibung ignoriert werden soll.
Die Option -q Sagt, dass nach dem ersten Spiel keine Ausgabe ausgegeben und beendet werden soll.
Die Option -F Sagt, dass das Argument als Zeichenfolge und nicht als regulärer Ausdruck behandelt werden soll.

Beachten Sie, dass im ersten Beispiel [ expression ] Verwendet wird, das direkte Vergleiche und verschiedene nützliche Operatoren ermöglicht. Das zweite Formular führt nur Befehle aus und testet ihren Exit-Status.

12
BobDoolittle

Mit dem Regex-Operator =~ können Sie in bash den Teilstring-Matching nativ ohne Berücksichtigung der Groß- und Kleinschreibung durchführen, wenn Sie die Shell-Option nocasematch festlegen. Zum Beispiel

s1="hElLo WoRlD"
s2="LO"

shopt -s nocasematch

[[ $s1 =~ $s2 ]] && echo "match" || echo "no match"
match

s1="gOoDbYe WoRlD"
[[ $s1 =~ $s2 ]] && echo "match" || echo "no match"
no match
49
steeldriver

Für eine Zeichenfolgensuche nach Groß- und Kleinschreibung des Werts der Variablen needle im Wert der Variablen haystack:

case "$haystack" in
  *"$needle"*) echo "present";
  *) echo "absent";
esac

Konvertieren Sie bei einer Zeichenfolgensuche ohne Berücksichtigung der Groß- und Kleinschreibung beide in denselben Fall.

uc_needle=$(printf %s "$needle" | tr '[:lower:]' '[:upper:]' ; echo .); uc_needle=${uc_needle%.}
uc_haystack=$(printf %s "$haystack" | tr '[:lower:]' '[:upper:]' ; echo .); uc_haystack=${uc_haystack%.}
case "$uc_haystack" in
  *"$uc_needle"*) echo "present";;
  *) echo "absent";;
esac

Beachten Sie, dass tr in GNU coreutils keine Multibyte-Gebietsschemas unterstützt (z. B. UTF-8). Verwenden Sie stattdessen awk, um mit Multibyte-Gebietsschemas arbeiten zu können Um awk zu verwenden, können Sie den Zeichenfolgenvergleich und nicht nur die Konvertierung durchführen.

if awk 'BEGIN {exit !index(toupper(ARGV[2]), toupper(ARGV[1]))}' "$needle" "$haystack"; then
  echo "present"
else
  echo "absent"
fi

Das tr von BusyBox unterstützt die Syntax [:CLASS:] Nicht. Sie können stattdessen tr a-z A-Z verwenden. BusyBox unterstützt keine Nicht-ASCII-Gebietsschemas.

In bash (aber nicht sh), Version 4.0+, gibt es eine integrierte Syntax für die Konvertierung von Groß- und Kleinschreibung und eine einfachere Syntax für den String-Abgleich.

if [[ "${haystack^^}" = *"${needle^^}"* ]]; then
  echo "present"
else
  echo "absent"
esac