Utilizzando match per trovare sottostringhe in stringhe con solo bash

Anche se sono quasi sicuro che questo è stato coperto, non riesco a trovare nulla di specifico per questo. Come continuare il mio viaggio di apprendimento bash continuo a trovare le parti in cui sono sconcertato perché le cose accadono in un certo modo.

La ricerca e la sostituzione o solo corrispondenza sotto-stringhe stringhe è più probabile che una delle prime cose che si fanno durante la scrittura di script. Ma, cercando di attenersi a un unico linguaggio, o un insieme di strumenti è difficile farlo in bash, come si è in grado di risolvere la maggior parte dei problema in più modi. Sto facendo del mio meglio per soggiorno il più basso livello possibile, con la bash. Ho eseguito in un intoppo che ho bisogno di qualcuno che mi spieghi.

Facendo sotto-stringa di ricerca in bash con partita mi dà risultati diversi a seconda dell’espressione regolare, che io uso, e non so perché.

#!/bin/bash
Stext="Hallo World"
echo `expr "$Stext" : '^\(.[a-z]*\)'` # Hallo
echo `expr "$Stext" : '.*World'`      # 11

Sebbene sia la ricerca di una parola, di penso, sia per non tornare a quello che si trova. Perché?

  • expr non è bash funzionalità-è uno strumento esterno che non è parte della shell. Di conseguenza, il suo comportamento non è garantito per essere coerente su una determinata versione di bash quando installati su diverse piattaforme, oltre le garanzie minime previste dalla sh standard POSIX (garanzie che non promettere la sintassi delle espressioni regolari di là BRE). Inoltre, essendo esterno, significa che è molto più lento da eseguire, che richiedono un fork() per dare il via a una subshell e un exec() di sostituire il guscio con un eseguibile esterno.

 

4 Replies
  1. 30

    Entrambe le espressioni sono equivalenti, la differenza è l’espressione regolare si utilizza:

    $ echo `expr "$Stext" : '^\(.[a-z]*\)'`
    Hallo
    $ echo `expr "$Stext" : '^.[a-z]*'`
    5
    $ echo `expr "$Stext" : '\(.*World\)'`
    Hallo World
    $ echo `expr "$Stext" : '.*World'`
    11

    Come si può vedere, tra le parentesi è quello che fa la differenza per ritornare la lunghezza della partita o la partita stessa.

    È possibile trovare ulteriori esempi in Capitolo 10 di Advanced Bash-Scripting Guide.

    • Grazie per la spiegazione semplice @jcollado 🙂 i documenti che hai fornito, ma in qualche modo non si ottiene questa parentesi funzionalità. Bash-Scripting guide non è troppo facile da digerire.
    • Come questa domanda è di circa bash, preferire l’uso di builtin regex come @kev suggeriscono invece di bivio per /usr/bin/expr!
  2. 67

    È possibile utilizzare il BASH_REMATCH variabile in bash per ottenere la stringa corrispondente:

    $ Stext="Hallo World"
    $ [[ $Stext =~ ^.[a-z]* ]] && echo $BASH_REMATCH
    Hallo
    $ [[ $Stext =~ ^(.[a-z]*) ]] && echo ${BASH_REMATCH[1]}
    Hallo

    Sottostringhe abbinati tra parentesi sottoespressioni nell’espressione regolare viene salvato nella variabile array BASH_REMATCH. L’elemento di BASH_REMATCH con indice 0 è la porzione di stringa corrispondente all’intera espressione regolare. L’elemento di BASH_REMATCH con indice n è la porzione di stringa corrispondente all’ennesima espressione parentetica.

    • … e [[ "Hello world" =~ ^[^\ ]* ]] && echo ${#BASH_REMATCH} -> 5
  3. -1

    Per una rapida stringa di ricerca … Una possibilità è grep.

    Se non si trova, restituisce il vuoto, il resto è un match:

    found=`echo $big | grep -e $short`
    
    if [ ! -z $found ]; then echo 'There is a match'; else echo 'No no'; fi

Lascia un commento