2013-03-19 18 views
21

Sto cercando di aggiungere una funzione al mio bash_profile per :Errore di sintassi = ~ operatore in bash msysgit

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

Ma ottengo il seguente errore:

bash: conditional binary operator expected`

bash: syntax error near =~'

Da quello che Posso trovare, l'operatore "equals tilde" (=~) valuta come regex in bash.

Perché =~ genera un errore?

UPDATE: Ecco uno screenshot di inserendo manualmente (questo sh.exe è in esecuzione):

Screenshot of equals tilde (=~) operator failing

+0

non c'è bisogno di citare o mettere regexp parentesi, basta usare per esempio '[[$ line = ~^$]]' –

+0

buona presa, che aspetto hai? e a cosa è '/ bin/sh' un link simbolico? –

+0

@FredrikPihl: Poiché questo è in 'bash_profile', dubito che ci sia uno shebang. – ruakh

risposta

7

Aggiornamento 2015: msysgit è ormai obsoleto.
È necessario utilizzare la bash fornita con git-for-windows.
Come indicato in this answer, utilizza una bash molto più recente (4.3+), per la quale funziona la sintassi =~.


risposta Originale (marzo 2013)

La bash confezionato con msysgit potrebbe semplicemente essere troppo vecchio per sostenere pienamente questo operatore.
E 'certamente troppo vecchio da confrontare con non quotate regex, come indicato nel "Bash, version 3" e "How do I use regular expressions in bash scripts?":

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

In realtà, mklement0 menzioni nei commenti:

=~ 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.

Ma ho provato con le virgolette (nell'ultimo msysgit 1.8.1.2), e non riesce ancora:

[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 "troppo vecchio per confrontarlo con espressioni regolari non quotate": '= ~' è stato introdotto in bash 3.0 e _always_ ha supportato un token _unquoted_ su RHS. Fino a 3.1.x, i token _quoted_ sono stati sottoposti a _treated lo stesso_ dei token non quotati: entrambi sono stati interpretati come regex. Ciò che è cambiato in 3.2 era che i token _quoted_ (o le sottostringhe quotate di un token) ora sono trattati come _literals_. – mklement0

+0

@ mklement0 buon punto. Ho incluso il tuo commento nella risposta per maggiore visibilità. – VonC

+0

Lo apprezzo, grazie. – mklement0

26

Ho avuto lo stesso errore su Bash 3.1.0 dall'installazione di Git su Windows. In definitiva ho cambiato in:

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

Funziona nel caso semplice, ma non per i gruppi di cattura. – Eris

13

Secondo https://groups.google.com/forum/#!topic/msysgit/yPh85MPDyfE questo è perché msys non viene fornito libregex con bash. Presumibilmente se si compila/trova un libregex compilato da msys e lo si inserisce nel percorso della libreria, =~ inizia a funzionare correttamente.

+1

Grande puntatore. Sfortunatamente, la semplice sostituzione di msys-regex-1.dll di msysgit con uno da MSYS non funziona. Cosa vuol dire _seem_ (provare a proprio rischio), è copiare i seguenti file dalla directory 'bin' di un'installazione MSYS alla directory' bin' di msysgit: 'bash.exe',' sh.exe', 'msys-termcap -0.dll' - in altre parole: sostituire bash del tutto. Tuttavia, a quel punto potresti anche usare MSYS direttamente, usando solo 'git.exe' da msysgit - vedi http://stackoverflow.com/q/5885393/45375 – mklement0

1

Ecco una soluzione che supporta l'estrazione di stringhe corrispondenti. Se l'operatore = ~ non è supportato da bash, il comando sed è usato (installato con msysgit) esempio

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 

Usage:

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

Nota che nessuno usa più msygit: ora è obsoleto e sostituito con git-for-windows (https://github.com/git-for-windows/git/releases), che ha una versione più recente di 4.x (http://stackoverflow.com/a/26826359/6309) – VonC

+0

Wow, non mi pento di passare a Linux. –

+0

@Vonc dopo aver affrontato questa follia per un po '(penso di averlo incontrato per la prima volta in agosto), ho appena preso git-for-windows per un giro e sono stupefatto di quanti degli stupidi fastidi che corregge vs. msysgit (es. mancanza di valori predefiniti di intellegent per Vim, mancanza di un terminale ridimensionabile, ecc.). Penso di aver iniziato a utilizzare msysgit nel 2011 o 2012 e non sapevo che ci fosse qualcosa di meglio (forse non c'era in quel momento?). Onestamente non so perché questo suggerimento è sepolto in un commento - forse dovresti considerare di renderlo una risposta? IMHO è la migliore risposta qui. –