2012-03-07 13 views
36

Chociaż jestem niemal pewien, że zostało to omówione, nie mogę znaleźć niczego konkretnego. Gdy kontynuuję swoją podróż po nauce bash, wciąż znajduję części, w których jestem zaskoczony, dlaczego rzeczy dzieją się tak, jak oni.Używanie dopasowywania do znajdowania podciągów w łańcuchach z tylko bashem

Wyszukiwanie i zamiana lub tylko dopasowywanie pod-łańcuchów w łańcuchach jest najprawdopodobniej jedną z pierwszych rzeczy, które robisz podczas pisania skryptów. Ale próbowanie trzymania się jednego języka lub zestawu narzędzi jest trudne do zrobienia w bashu, ponieważ jesteś w stanie rozwiązać większość problemów na wiele sposobów. Robię, co w mojej mocy, aby z bashiem pozostać jak najniższym poziomem. Wpadłem w szkopuł, że potrzebuję kogoś, kto mi wytłumaczy.

Wykonywanie pod-ciągu wyszukiwania w bashie z dopasowaniem daje mi różne wyniki w zależności od wyrażenia regularnego, którego używam, i nie jestem pewien dlaczego.

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

Chociaż zarówno wyszukać słowo, myślę, zarówno nie wracają co Kowalski. Czemu?

Odpowiedz

23

Oba wyrażenia są równoważne, różnica jest wyrażenie regularne użyć:

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

Jak widać, nawiasów, co czyni różnicę albo powrócić długość meczu lub samego meczu.

Możesz znaleźć więcej przykładów w Chapter 10 w Advanced Bash-Scripting Guide.

+0

Dzięki za proste wyjaśnienie @jcollado :) używałem docs że przewidziane, ale jakoś nie dostać ten nawiasach funkcjonalności. Przewodnik Bash-Scripting nie jest zbyt łatwy do strawienia. –

+1

Ponieważ to pytanie dotyczy [tag: bash], najlepiej użyć * wbudowanego * regex jako [@kev suggest] (http://stackoverflow.com/a/9602260/1765658) zamiast * fork do '/ usr/bin/expr' *! –

49

Można użyć zmiennej BASH_REMATCH w bash aby uzyskać dopasowany ciąg:

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

Podciągi dopasowane nawiasach podwyrażeń w wyrażeniu regularnym są zapisywane w zmiennej tablicowej BASH_REMATCH. Element BASH_REMATCH z indeksem 0 jest częścią ciągu pasującego do całego wyrażenia regularnego. Element BASH_REMATCH z indeksem n jest częścią ciągu pasującego do n-tego nawiasowanego podwyrażenia.

+0

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

0

Zrobiłem tę prostą funkcję:

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

Zastosowanie:

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

cały kod: https://gist.github.com/TeeBSD/5121b3711fad40a09455

+0

ten wpis nie ma rzeczywistego znaczenia dla pytania lub odpowiedzi. –

0

Do szybkiego wyszukiwania smyczkowych ... Jedną z opcji jest grep.
Jeśli nie znaleziono, zwraca pusty, inaczej jest to mecz:

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

if [ ! -z $found ]; then echo 'There is a match'; else echo 'No no'; fi 
Powiązane problemy