komenda expr bash zwracająca 0 w ocenie podłańcucha

0

Próbuję odczytać linię z pliku, zapisać ją w zmiennej $ line i wyodrębnić wszystkie instancje (tzn. Nawiasy kątowe tylko dużymi literami). Próbuję:

while read line
do
#some other commands
FOUND=`expr $line : \<[A-Z]*\>`
echo FOUND is:$FOUND
#more commands

Po uruchomieniu skryptu zasilam go:

<hello><HELLO>

wydajność:

FOUND is:0

Wypróbowałem również wariacje na temat cytatów wokół bitu regex. to znaczy "\<[A-Z]*\>" , '\<[A-Z]*\>' i \(<[A-Z]*>\)gdzie ostatni z tych zwraca null.

Sprawdziłem stronę podręcznika, powinna ona zwracać 0, jeśli pasuje zero znaków lub jeśli mecz się nie powiedzie. Czuję, że to coś małego, co przeoczyłem, ale po godzinie poszukiwań wciąż nie mogę tego zrozumieć.

Każda pomoc zatwierdzona

Kyle Cochran
źródło

Odpowiedzi:

0

Sprawdź exprstronę podręcznika : wyrażenia regularne są niejawnie zakotwiczone , więc jeśli twoja linia $ nie zaczyna się od wielkiej litery w nawiasach, expr nie znajdzie jej

line="<hello><HELLO>"
expr "$line" : '.*<[[:upper:]]*>'       # => 14
expr "$line" : '.*\(<[[:upper:]]*>\)'   # => <HELLO>

ref: https://www.gnu.org/software/coreutils/manual/html_node/String-expressions.html

Zauważ, że exprnie jest to polecenie bash, to osobny program. Jeśli chcesz to zrobić w bashu:

if [[ "$line" =~ "<"[[:upper:]]*">" ]]; then
    echo "found it"
    echo "${BASH_REMATCH[0]}"
fi

Podaj również swoje zmienne

Glenn Jackman
źródło
Niesamowite. To działa, dzięki. Co to za =~operator? Nie mogę go znaleźć na liście operatorów porównania bash. Czy jest to forma „zawiera”?
Kyle Cochran
Jest to operator dopasowywania wyrażeń regularnych. Domyślam się, że ukradli go perlowi, który prawdopodobnie ukradł go z awk. Udokumentowane [[...]]poleceniem
glenn jackman
Czy istnieje sposób na użycie tego podejścia do znalezienia wielu wystąpień wzoru w linii? Z tego, co rozumiem, BASH_REMATCH jest zdefiniowany w podpowłoce, więc nie jestem w stanie iterować procesu.
Kyle Cochran
BASH_REMATCH to po prostu zwykła zmienna (tablica), zadeklarowana w bieżącej powłoce. Dla wielu meczów: if [[ "$line" =~ pattern1 ]] || [[ "$line" =~ pattern2 ]] || [[ "$line" =~ pattern3 ]] ...lub możesz sprytnie połączyć wszystkie wzory w jedno wyrażenie regularne, ale to może szybko stać się nieczytelne
glenn jackman