Lazy Regex mit Bash

Lazy Regex mit Bash

Ich versuche, mithilfe der in Bash integrierten Regex-Funktion nur den Text abzugleichen, der innerhalb der HTML-Tags enthalten ist:

string='<span class="circle"> </span>foo</span></span>'
regex='<span class="circle"> </span>(.+?)</span>'
[[ $string =~ $regex ]]
echo "${BASH_REMATCH[1]}"

Aber das Spiel fesselt immer wieder foo</span>.

Im Internet gibt es so viele Beispiele für sed und grep, dass ich zu Bashs eigenem regulären Ausdruck nicht viel Dokumentation gefunden habe.

Antwort1

Es gibt einen Grund, warum das Internet voll von alternativen Ansätzen ist. Ich kann mir keine Situation vorstellen, in der Siegezwungenum hierfür Bash zu verwenden. Warum nicht eines der für diese Aufgabe entwickelten Tools verwenden?

Wie dem auch sei, soweit ich weiß, gibt es keine Möglichkeit, mit dem =~Operator nicht-gierige Übereinstimmungen zu erzielen. Das liegt daran, dass er nicht die interne Regex-Engine von Bash verwendet, sondern die C-Engine Ihres Systems, wie in definiert man 3 regex. Dies wird in erklärt man bash:

   An additional binary operator, =~, is available, with the  same  prece‐
   dence  as  ==  and !=.  When it is used, the string to the right of the
   operator is considered  an  extended  regular  expression  and  matched
   accordingly  (as  in  regex(3)).  

Sie können jedoch mehr oder weniger tun, was Sie wollen (wobei Sie bedenken müssen, dass dies wirklichnichteine gute Möglichkeit zum Parsen von HTML-Dateien) mit einem leicht anderen regulären Ausdruck:

string='<span class="circle"> </span>foo</span></span>'
regex='<span class="circle"> </span>([^<]+)</span>'
[[ $string =~ $regex ]]; 
echo "${BASH_REMATCH[1]}"

Das Obige wird foowie erwartet zurückgegeben.

Antwort2

Ich weiß nicht, ob die regulären Ausdrücke von Bash nicht gierig übereinstimmen wie Perl, also verwenden Sie eine Perl-Regex-Engine:

$ grep -oP '<span class="circle"> </span>\K.+?(?=</span>)' <<<"$string"
foo

verwandte Informationen