2012-03-07 10 views
36

Sebbene sia quasi sicuro che questo è stato coperto, non riesco a trovare nulla di specifico a questo. Mentre continuo il mio viaggio sull'apprendimento bash continuo a cercare parti in cui sono sconcertato sul perché le cose accadano nel modo in cui lo fanno.Utilizzo della corrispondenza per trovare sottostringhe nelle stringhe con solo bash

Cercare e sostituire o semplicemente associare le stringhe secondarie nelle stringhe è molto probabilmente una delle prime cose che si fanno durante la scrittura degli script. Ma cercare di attenersi a una sola lingua o serie di strumenti è difficile da fare in bash, dato che sei in grado di risolvere la maggior parte dei problemi in più modi. Sto facendo del mio meglio per rimanere il più basso livello possibile con bash. Ho incontrato un problema che ho bisogno di qualcuno che mi spieghi.

Fare una sottostringa con una ricerca in bash con corrispondenza mi dà risultati diversi a seconda dell'espressione regolare che utilizzo e non sono sicuro del perché.

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

Anche se entrambi ricerca di una parola, penso, entrambi non restituiscono quello che trovano. Perché?

risposta

23

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, parentesi è ciò che fa la differenza a uno restituire la lunghezza della partita o la partita in sé.

È possibile trovare altri esempi in Chapter 10 della Guida avanzata di Bash-Scripting.

+0

Grazie per la semplice spiegazione @jcollado :) Stavo usando i documenti che hai fornito, ma in qualche modo non ha ottenuto questa parentesi funzionalità. La guida di Bash-Scripting non è troppo facile da digerire. –

+1

Poiché questa domanda riguarda [tag: bash], preferisci usare * builtin * regex come [@kev suggerire] (http://stackoverflow.com/a/9602260/1765658) invece di * fork in '/ usr/bin/expr' *! –

49

È possibile utilizzare la variabile BASH_REMATCH 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 appaiati per sottoespressioni tra parentesi all'interno dell'espressione regolare vengono salvati nella variabile array BASH_REMATCH. L'elemento di BASH_REMATCH con indice 0 è la parte della stringa che corrisponde all'intera espressione regolare. L'elemento di BASH_REMATCH con indice n è la porzione della stringa che corrisponde alla nesima sottoespressione parentesi.

+0

... e '[[" Hello world "= ~^[^ \] *]] && echo $ {# BASH_REMATCH}' -> '5' ... –

0

ho fatto questa semplice funzione:

match() { 
    TRUE=1 
    FALSE=0 
    match_return=0 
    echo $1 | grep $2 >/dev/null 
    [ $? -eq 0 ] && match_return=$TRUE || match_return=$FALSE 
} 

Usage:

match Testing Test ; [ $match_return -eq 1 ] && echo "match!" || echo "nope" 

intero codice: https://gist.github.com/TeeBSD/5121b3711fad40a09455

+0

questo post non ha alcuna rilevanza per la domanda o la risposta. –

0

Per le ricerche di stringa rapide ... Una possibilità è grep.
Se non trovato, le corse a vuoto, altrimenti si tratta di una partita:

found=`echo $big | grep -e $short` 

if [ ! -z $found ]; then echo 'There is a match'; else echo 'No no'; fi 
Problemi correlati