Groß- / Kleinschreibung wird in einem Shell-Skript nicht berücksichtigt [closed]

22

Wie kann ich ein Shell-Skript schreiben, bei dem bei der Befehlsausgabe die Groß- und Kleinschreibung nicht berücksichtigt wird?

Miguel Roque
quelle
grep -ivielleicht?
Ramesh
Wie werde ich das in mein Skript einfügen? Es tut mir leid, wenn dies eine Anfängerfrage ist. Ich fange gerade erst an, Linux zu lernen, weil ich es für mein Praktikum brauche. Vielen Dank!
Miguel Roque
1
Was Sie fragen, ist Shell-Scripting - "Linux" ist keine Programmiersprache, sondern ein Betriebssystemkernel. Die unter Linux am häufigsten verwendete Shell bashist eine Obermenge des Unix-Standardssh . Sie können mit einem der folgenden Schritte beginnen: | 1 | | 2 | - nur um den tatsächlichen Kontext in den Griff zu bekommen.
Goldlöckchen
1
Diese Frage scheint jetzt ziemlich klar zu sein und entspricht den Richtlinien in der Hilfe. Kann es bitte für andere geöffnet werden?
BobDoolittle
2
Ich verstehe nicht, warum diese Frage nicht klar ist. Was muss ich hinzufügen, damit es klar ist?
Miguel Roque

Antworten:

11

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, die Zeichenfolge Hallo auf der rechten Seite zu ändern, und es sollte nicht mehr widerhallen it works. Versuchen Sie, echo hellodurch einen Befehl Ihrer Wahl zu ersetzen . Wenn Sie die Groß- / Kleinschreibung ignorieren möchten und keiner der beiden Strings 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 weiterleiten grep. Die ifAnweisung testet den Beendigungsstatus des Befehls ganz rechts in einer Pipeline - in diesem Fall grep. Grep beendet sich nur dann mit Erfolg, wenn es eine Übereinstimmung findet.

Die -iOption von grep sagt, Groß- und Kleinschreibung zu ignorieren.
Die -qOption besagt, dass nach dem ersten Treffer keine Ausgabe erfolgen soll.
In der -FOption wird angegeben, dass das Argument als Zeichenfolge und nicht als regulärer Ausdruck behandelt werden soll.

Beachten Sie, dass das erste Beispiel direkte Vergleiche und verschiedene nützliche Operatoren ermöglicht. Die zweite Form führt nur Befehle aus und testet ihren Exit-Status.[ expression ]

BobDoolittle
quelle
Ich verstehe nicht, warum Gilles es für notwendig hielt, den von mir beigetragenen Code zu ändern. Er hat nichts kaputt gemacht, aber es hat gut funktioniert. In diesem Beispiel benötigen Sie keine doppelten Anführungszeichen. Diese sind jedoch wichtig, wenn die Ausgabe Leerzeichen enthält. Und == funktioniert genauso gut wie =, weil sh tatsächlich auf Linux bash ist. Die ursprüngliche Bourne-Shell ist zu diesem Zeitpunkt schon lange nicht mehr vorhanden. Ich glaube nicht, dass Solaris es mehr ausliefert. In diesem Beispiel bin ich zwar nicht der Meinung, dass doppelte Anführungszeichen wahrscheinlich eine bewährte Methode sind, aber meiner Meinung nach ist dies auch '==', um Zuordnung und Vergleich klar voneinander zu trennen.
BobDoolittle
Warten Sie, damit man einen Beitrag bearbeiten kann? Ich wusste das nicht.
Miguel Roque
Mit ausreichendem Ruf, ja. Ich würde mir wünschen, dass jemand mit hohem Ansehen zweimal überlegt, bevor er unnötige Änderungen vornimmt, insbesondere, um Code in diesem Forum zu erstellen. unix.stackexchange.com/help/privileges
BobDoolittle
@BobDoolittle Es mag in bestimmten Fällen einen Unterschied machen, aber nicht bei Ihrem Setup - es ist gut zu wissen.
1
Beachten Sie, dass es in der Praxis nicht nur um die Bourne-Shell geht. ==ist nicht POSIX. shist nicht bashauf allen Linux-basierten Systemen. ==wird nicht unterstützt von ash(worauf shzumindest die von vielen BSDs und Debian-Derivaten basieren), oder poshund muss in zitiert werden zsh. Es macht keinen Sinn, das zu verdoppeln =. [ist ein Befehl zum Testen. Hier muss nicht zwischen Zuordnung und Vergleich unterschieden werden. Das ist etwas anderes in (( a == b ))vs (( a = b)). Die Verwendung ==in einem Skript, das mit beginnt, #! /bin/shist falsch. Wenn Sie davon ausgehen, kshoder bashSyntax, aktualisieren Sie die #!entsprechend.
Stéphane Chazelas
49

Wenn Sie die Shell-Option festlegen, können Sie den Teilstring-Abgleich ohne Berücksichtigung der Groß- und Kleinschreibung nativ bashmithilfe des Regex-Operators durchführen . Beispielsweise=~nocasematch

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
Stahlfahrer
quelle
6
lol! Punkte für obskures Shell-Wissen.
BobDoolittle
1
Diese Option wirkt sich auch auf den Operator für einfache Übereinstimmungen aus. [[ XYZ == xyz ]] && echo "match"=>match
itsadok
6

Bei einer Zeichenfolgensuche, bei der die Groß- und Kleinschreibung beachtet wird, wird der Wert der Variablen needleim Wert der Variablen wie folgt gesucht haystack:

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

Konvertieren Sie für eine Suche nach Zeichenfolgen, bei der die Groß- und Kleinschreibung nicht beachtet wird, beide in dieselbe Groß- / Kleinschreibung.

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 die trin GNU Coreutils keine Multibyte-Locales unterstützen (zB UTF-8). Verwenden Sie stattdessen awk, um mit Multibyte-Gebietsschemas zu arbeiten. Wenn Sie awk 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

Die trfrom BusyBox unterstützt die Syntax nicht. Sie können stattdessen verwenden. BusyBox unterstützt keine Nicht-ASCII-Sprachumgebungen.[:CLASS:]tr a-z A-Z

In bash (aber nicht in sh) 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
Gilles 'SO - hör auf böse zu sein'
quelle
Mir ist klar, dass dies ein paar Jahre alt ist, aber all das printf | trlässt meinen Kopf herumwirbeln. Wenn möglich, beschränken Sie Ihren Aufruf von Befehlen auf ein Minimum. Mit einer Variablen v können Sie dasselbe erreichen v=$(tr '[:lower:]' '[:upper:]' <<<$v). Für diejenigen, die es noch nie zuvor gesehen haben, ist das <<<im Wesentlichen eine "Hier-Variable", wie die Verwendung <<EOFfür ein Hier-Dokument. Tu es nicht printfoder nur, echowenn du es unbedingt tun musst.
Will
@ Will Das funktioniert nur in Shells, die den <<<Operator haben: ksh, bash, zsh, aber nicht plain sh. Und es ist ziemlich nah dran, printfwie es läuft: Es gibt die gleiche Anzahl von Aufrufen zu forkund execve(vorausgesetzt, das printfist eingebaut, was bei den meisten gebräuchlichen Shells der Fall ist); Ein Unterschied besteht darin, dass <<<eine temporäre Datei erstellt wird, anstatt eine Pipe zu verwenden. <<<ist bequem zu tippen, aber keine Leistungsverbesserung.
Gilles 'SO- hör auf böse zu sein'