it-swarm.com.de

bash-Regex-Übereinstimmungszeichenfolge

Ich versuche, ein Bash-Skript zu schreiben, das eine Funktion enthält. Wenn eine .tar-, .tar.bz2-, .tar.gz usw. -Datei angegeben wird, verwendet es tar mit den entsprechenden Schaltern, um die Datei zu dekomprimieren.

Ich verwende if Elif then -Anweisungen, die den Dateinamen testen, um zu sehen, worauf er endet, und ich kann nicht mit Regex-Metazeichen übereinstimmen.

Um das Skript, das ich "test" in der Befehlszeile verwende, ständig umzuschreiben, zu speichern, dachte ich, dass die folgende Anweisung funktionieren sollte. Ich habe jede mögliche Kombination von Klammern, Anführungszeichen und Metacharatern ausprobiert, und trotzdem schlägt sie fehl.

test sed-4.2.2.tar.bz2 = tar\.bz2$; echo $?
(this returns 1, false)

Ich bin mir sicher, dass das Problem ein einfaches ist und ich habe überall gesucht, aber ich kann nicht verstehen, wie es geht. Weiß jemand, wie ich das machen kann?

123
user1587462

Um Ausdrücke abzugleichen, müssen Sie den Operator =~ verwenden.

Versuche dies:

[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo matched

Alternativ können Sie Platzhalter (anstelle von Regex) mit dem Operator == verwenden:

[[ sed-4.2.2.tar.bz2 == *tar.bz2 ]] && echo matched

Wenn die Portabilität kein Problem darstellt, empfehle ich die Verwendung von [[ anstelle von [ oder test, da dies sicherer und leistungsfähiger ist. Siehe Was ist der Unterschied zwischen test [und [[? für Details.

205
dogbane

Eine Funktion, um dies zu tun

extract () {
  if [ -f $1 ] ; then
      case $1 in
          *.tar.bz2)   tar xvjf $1    ;;
          *.tar.gz)    tar xvzf $1    ;;
          *.bz2)       bunzip2 $1     ;;
          *.rar)       rar x $1       ;;
          *.gz)        gunzip $1      ;;
          *.tar)       tar xvf $1     ;;
          *.tbz2)      tar xvjf $1    ;;
          *.tgz)       tar xvzf $1    ;;
          *.Zip)       unzip $1       ;;
          *.Z)         uncompress $1  ;;
          *.7z)        7z x $1        ;;
          *)           echo "don't know '$1'..." ;;
      esac
  else
      echo "'$1' is not a valid file!"
  fi
}

Andere Anmerkung

In Antwort auf Aquarius Power in dem Kommentar oben, We need to store the regex on a var

Die Variable BASH_REMATCH wird gesetzt, nachdem Sie den Ausdruck gefunden haben, und $ {BASH_REMATCH [n]} stimmt mit der in Klammern eingeschlossenen n-ten Gruppe überein, dh in den folgenden ${BASH_REMATCH[1]} = "compressed" und ${BASH_REMATCH[2]} = ".gz"

if [[ "compressed.gz" =~ ^(.*)(\.[a-z]{1,5})$ ]]; 
then 
  echo ${BASH_REMATCH[2]} ; 
else 
  echo "Not proper format"; 
fi

(Der obige Regex ist nicht als gültiger Ausdruck für Dateinamen und Erweiterungen gedacht, funktioniert aber für das Beispiel.)

43
duality

Ich habe nicht genug Repräsentanten, um hier einen Kommentar abzugeben, deshalb sende ich eine neue Antwort, um die Antwort von Dogbane zu verbessern. Der Punkt . in der Regexp 

[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo matched 

wird tatsächlich mit jedem Zeichen übereinstimmen, nicht nur mit dem wörtlichen Punkt zwischen 'tar.bz2'

[[ sed-4.2.2.tar4bz2 =~ tar.bz2$ ]] && echo matched
[[ sed-4.2.2.tar§bz2 =~ tar.bz2$ ]] && echo matched

oder irgendetwas, das nicht mit '\' .. zu maskieren ist .. Die strikte Syntax sollte dann sein

[[ sed-4.2.2.tar.bz2 =~ tar\.bz2$ ]] && echo matched

oder Sie können noch strenger gehen und auch den vorherigen Punkt in den Regex einfügen:

[[ sed-4.2.2.tar.bz2 =~ \.tar\.bz2$ ]] && echo matched
6
user2066480

Da Sie bash verwenden, müssen Sie dafür keinen untergeordneten Prozess erstellen. Hier ist eine Lösung, die es vollständig innerhalb von bash ausführt:

[[ $TEST =~ ^(.*):\ +(.*)$ ]] && TEST=${BASH_REMATCH[1]}:${BASH_REMATCH[2]}

Erläuterung: Die Gruppen vor und nach der Sequenz "Doppelpunkt und ein oder mehrere Leerzeichen" werden vom Musteranpassungsoperator im Array BASH_REMATCH gespeichert.

2
user1934428
if [[ $STR == *pattern* ]]
then
    echo "It is the string!"
else
    echo "It's not him!"
fi

Funktioniert bei mir! GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)

0
juan cortez

shopt -s nocasematch

if [[ sed-4.2.2.$LINE =~ (yes|y)$ ]]
 then exit 0 
fi
0
Shyam Gupta