2013-03-19 13 views
21

Próbuję dodać funkcję do mojego bash_profile dla :Błąd składni = ~ operator w msysgit bash

function git-unpushed { 
    brinfo=$(git branch -v | grep git-branch-name) 
    if [[ $brinfo =~ ("[ahead "([[:digit:]]*)]) ]] 
    then 
     echo "(${BASH_REMATCH[2]})" 
    fi 
} 

Ale pojawia się następujący błąd:

bash: conditional binary operator expected`

bash: syntax error near =~'

od tego, co Mogę stwierdzić, że operator "równa się tylda" (=~) jest oceniany jako regex w bashu.

Dlaczego =~ wyświetla błąd?

UPDATE: Oto zrzut ekranu wprowadzania go ręcznie (to działa sh.exe):

Screenshot of equals tilde (=~) operator failing

+0

ma potrzeby cytować lub umieścić regexp w nawiasach, po prostu użyć na przykład '[[$ line = ~^$]]' –

+0

dobry połów, jak wyglądasz? i czym jest "/ bin/sh' a dowiązaniem symbolicznym? –

+0

@FredrikPihl: Ponieważ jest to w 'bash_profile', wątpię, by był shebang. – ruakh

Odpowiedz

7

Aktualizacja 2015: msysgit jest już nieaktualne.
Powinieneś użyć bashu, który jest dostarczany z git-for-windows.
Jak wspomniano w artykule this answer, używa on znacznie nowszego bashu (4.3+), dla którego będzie działać składnia =~.


Original odpowiedź (marzec 2013),

Bash pakowane msysGit może być po prostu zbyt stary, aby w pełni obsługuje tego operatora.
Jest to z pewnością zbyt stary porównać z cytowane regex, jak wspomniano w "Bash, version 3" i "How do I use regular expressions in bash scripts?":

As of version 3.2 of Bash, expression to match no longer quoted.

Właściwie mklement0 wspomina w komentarzach:

=~ was introduced in bash 3.0 and always supported an unquoted token on the RHS.
Up to 3.1.x, quoted tokens were treated the same as unquoted tokens: both were interpreted as regexes.
What changed in 3.2 was that quoted tokens (or quoted substrings of a token) are now treated as literals.

Ale próbowałem z cytatami (w najnowszym pliku msysgit 1.8.1.2) i nadal nie działa:

[email protected]/
$ /bin/bash --version 
GNU bash, version 3.1.0(1)-release (i686-pc-msys) 
Copyright (C) 2005 Free Software Foundation, Inc. 
[email protected]/
$ variable="This is a fine mess." 
[email protected]/
$ echo "$variable" 
This is a fine mess. 
[email protected]/
$ if [[ "$variable" =~ T.........fin*es* ]] ; then echo "ok" ; fi 
bash: conditional binary operator expected 
bash: syntax error near `=~' 
[email protected]/
$ if [[ "$variable" =~ "T.........fin*es*" ]] ; then echo "ok" ; fi 
bash: conditional binary operator expected 
bash: syntax error near `=~' 
[email protected]/
+1

Re "za stary, by porównać z niecytowanym regexem": '= ~' został wprowadzony w bash 3.0 i _always_ obsłużył _unquoted_ token na RHS. Do 3.1.x, _quoted_ tokens zostały potraktowane tak samo jak niecytowane tokeny: oba zostały zinterpretowane jako regexes. W punkcie 3.2 zmieniono to, że _quoted_ tokeny (lub cytowane podciągi tokena) są teraz traktowane jako _literals_. – mklement0

+0

@ mklement0 dobry punkt. Włączyłem Twój komentarz w odpowiedzi, aby uzyskać lepszą widoczność. – VonC

+0

Doceniam to, dzięki. – mklement0

26

Miałem ten sam błąd w Bash 3.1.0 z instalacji Git w systemie Windows. Ostatecznie zmieniłem go na adres:

if echo $var | grep -E 'regexp' > /dev/null 
then 
    ... 
fi 
+9

Działa to w prostym przypadku, ale nie w grupach przechwytywania. – Eris

13

Według https://groups.google.com/forum/#!topic/msysgit/yPh85MPDyfE to dlatego Msys nie jest dostarczany wraz z libregex bash. Podobno jeśli skompilujesz/znajdziesz libregex wbudowany w msys i umieścisz go w ścieżce biblioteki, =~ zacznie działać poprawnie.

+1

Świetny wskaźnik. Niestety, po prostu zastąpienie 'msys-regex-1.dll' programu msysgit innym z MSYS _nie_ działa. Co robi _seem_ do pracy (spróbuj na własne ryzyko), to kopiowanie następujących plików z katalogu 'bin' instalacji MSYS do katalogu' bin' w msysgit: 'bash.exe',' sh.exe', 'msys-termcap -0.dll "- innymi słowy: wymień całkowicie bash. Jednak w tym momencie możesz równie dobrze użyć MSYS bezpośrednio, używając tylko 'git.exe' z msysgit - patrz http://stackoverflow.com/q/5885393/45375 – mklement0

1

Oto rozwiązanie, które obsługuje wyodrębnianie pasujących ciągów. Jeżeli operator = ~ nie jest obsługiwany przez bash, a następnie stosuje się sed poleceń (instalowane z msysGit) przykład

if eval "[[ a =~ a ]]" 2>/dev/null; then 
    regexMatch() { # (string, regex) 
     eval "[[ \$1 =~ \$2 ]]" 
     return $? 
    } 
elif command -v /bin/sed >/dev/null 2>&1; then 
    regexMatch() { # (string, regex) 
     local string=$1 
     if [[ ${2: -1} = $ ]]; then 
      local regex="(${2%$})()()()()()()()()$" 
     else 
      local regex="($2)()()()()()()()().*" 
     fi 
     regex=${regex//\//\\/} 
     local replacement="\1\n\2\n\3\n\4\n\5\n\6\n\7\n\8\n\9\n" 
     local OLD_IFS=$IFS 
     IFS=$'\n' 
     BASH_REMATCH=($(echo "$string" | /bin/sed -rn "s/$regex/$replacement/p" | while read -r; do echo "${REPLY}"; done)) 
     IFS=$OLD_IFS 
     [[ $BASH_REMATCH ]] && return 0 || return 1 
    } 
else 
    error "your Bash shell does not support regular expressions" 
fi 

Zastosowanie:

if regexMatch "[email protected]" "(.+)@(.+)"; then 
    echo ${BASH_REMATCH[0]} 
    echo ${BASH_REMATCH[1]} 
    echo ${BASH_REMATCH[2]} 
fi 
+2

Pamiętaj, że nikt już nie używa msygit: jest już przestarzały i zastąpione przez git-for-windows (https://github.com/git-for-windows/git/releases), który ma znacznie nowszy bash 4.x (http://stackoverflow.com/a/26826359/6309) – VonC

+0

Wow, nie żałuję przejścia na Linuksa. –

+0

@Vonc po uporaniu się z tym szaleństwem przez chwilę (myślę, że pierwszy raz spotkałem go w sierpniu), po prostu wziąłem git-for-windows za spin i jestem zdumiony tym, jak wiele z głupich irytacji to rozwiązuje vs. msysgit (np. brak jakiejkolwiek inteligencji domyślnej dla vima, brak skalowalnego terminala, itp.). Myślę, że zacząłem używać msysgit w 2011 lub 2012 i nie wiedziałem, że było coś lepszego (być może nie było wtedy?). Szczerze mówiąc nie wiem, dlaczego ta sugestia jest pochowana w komentarzu - może powinieneś rozważyć zrobienie tego jako odpowiedź? IMHO to najlepsza odpowiedź tutaj. –