Shell-Test, um ein Muster in einer Zeichenfolge zu finden

8

Ich wollte nur fragen, ob es einen Befehl gibt, der für gängige Muscheln (Bash, Dash, Kornshell) funktioniert. Es soll prüfen, ob die lineVariable einen Teil des Pfades enthält.

if [[ $line =~ "$PWD"$ ]] ;then
applenisch
quelle
Hast du das versucht? Dieser Befehl funktioniert in modernen Bash-Shells genau so, wie Sie ihn eingegeben haben.
Terdon
Das wird nicht im Strich funktionieren.
Jonathan Leffler

Antworten:

4

Ja, neuere Versionen von bash können dies:

$ pwd
/home/terdon
$ line="I'm in /home/terdon"
$ [[ "$line" =~ "$PWD"$ ]] && echo yes
yes

Die gleiche Syntax funktioniert in zsh und ksh, jedoch nicht in Bindestrich. Soweit ich weiß, hat dash keine solchen Fähigkeiten.

Beachten Sie, dass Ihre Regex , ob die Variable prüft $line Enden mit $PWD. Entfernen Sie $PWDFolgendes $line, um zu überprüfen, ob irgendwo Übereinstimmungen vorhanden sind $:

$ line="I'm in /home/terdon, are you?"
$ [[ "$line" =~ "$PWD" ]] && echo yes
yes
terdon
quelle
1
Nein, diese funktionieren nur in bash-3.2 und höher, sofern die Option compatible31 nicht aktiviert wurde oder ksh93. In anderen Bash-Versionen oder zsh funktioniert es nicht richtig, wenn $ PWD Operatoren für reguläre Ausdrücke enthält.
Stéphane Chazelas
@ StéphaneChazelas Ja, deshalb habe ich angegeben, dass neuere Versionen von Bash dies können. Was den Rest angeht , ich habe gerade versucht in /home/terdon/foomit zsh, kshund bash(4.3.25) , und es hat gut funktioniert mit allen von ihnen. Es bricht tatsächlich ab, wenn es PWDRegex-Operatoren enthält. Das war mir einfach nie in den Sinn gekommen, danke!
Terdon
14

In jeder POSIX-kompatiblen Shell können Sie Folgendes tun:

case $line in (*"$PWD"*)
#    whatever your then block had
;;esac

Dies funktioniert in bash, dashund fast jeder anderen Shell, die Sie benennen können.

Es kann auch verwendet werden, um mehrere Möglichkeiten einfach zu handhaben. Zum Beispiel:

case $line in 
(*"$PWD"*)
    echo \$PWD match\!
;;
(*"$OLDPWD"*)
    echo \$OLDPWD match\!
;;
(*)
    ! echo no match\!
;;esac

Sie können auch alternieren:

case $line in (*"$PWD"*|*"$OLDPWD"*)
    echo '$OLDPWD|$PWD match!'
;;esac

Beachten Sie die Verwendung des obigen Zitats:

  1. case $line ...
    • Das Objekt einer caseAnweisung wird weder aufgeteilt $IFSnoch als Muster für den Dateinamen gen verwendet. Dies ähnelt der Art und Weise, wie das linke Argument in einem [[Test behandelt wird.
  2. (*"$PWD"*)
    • Auch hier wird eine Shell-Erweiterung weder einer $IFSDateinamen- noch einer Dateinamengenerierung unterzogen - eine nicht zitierte Erweiterung wird weder geteilt noch global.
    • Eine nicht zitierte Erweiterung kann hier jedoch eher als Muster als als wörtliche Zeichenfolge ausgelegt werden, und daher kann eine Erweiterung mehr als eine Sache bedeuten, je nachdem, ob sie zitiert wird oder nicht.
    • Es ist wichtig, alle in einem Muster verwendeten Variablen zu zitieren, die wörtlich interpretiert werden sollen, genauso wie Sie Musterzeichen zitieren würden, die Sie wörtlich interpretieren wollten.
    • Wenn beispielsweise $PWDein *und enthalten ist und nicht in Anführungszeichen steht, wird es als Musterobjekt und nicht als *zu durchsuchendes Literal ausgelegt .
mikeserv
quelle
@terdon - Sie hatten recht - der :Kommentar war verwirrend, aber ich habe es , weil es nicht gen einen Syntaxfehler hat oder versehentlich etwas proggie läuft namens was auch immer in $PATH. Auf diese Weise entsteht immer noch ein Syntaxfehler, aber zumindest ist klar, dass dies der Fall sein sollte.
Mikeserv
2
Beachten Sie, dass Sie, wenn Sie Portabilität mit der Bourne-Shell benötigen (zum Beispiel für einige alte Systeme), (case $line in *"$PWD"*)
Folgendes löschen
@ StéphaneChazelas - stimmt, aber wenn du das tust, zshwürgst du daran.
Mikeserv
1
Was meinst du? Beziehen Sie sich auf Dinge wie $(case a in a);; esac)?
Stéphane Chazelas
@ StéphaneChazelas - Ich kann es nicht reproduzieren, es sei denn, ich mache das Befehls-Sub wie in Ihrem Beispiel. Es ist auch komisch - zsh -cx '(case $1 in $2*) echo ok;;esac)' -- one ofunktioniert, aber das Präfix a : $bricht es. Ich denke, das ist das Problem, auf das ich in der Vergangenheit gestoßen bin - es war immer ein wenig unklar, und ich habe es nie zu genau betrachtet, weil das Hinzufügen ganz links es (immer behoben hat. Schließlich schrieb ich es einfach als eine seltsame zshSache ab und machte es zur Regel, beide Enden zu verwenden.
Mikeserv