Extrahieren einer Zeichenfolge nach einem Muster in einem Bash-Skript


17

Angenommen, ich habe eine Zeichenfolge strname:

strname="ph7go04325r"

Ich möchte die Zeichen zwischen dem ersten "3" und dem letzten "r" Zeichen in extrahieren und strnamedas Ergebnis in einer Zeichenfolge speichern strresult. Im obigen Beispiel strresultwäre das Ergebnis :

strresult="25"

Das erste "3"Zeichen muss sich nicht unbedingt an der Zeichenfolgeposition 8 in befinden strname. ebenfalls der letzte "r"ist nicht an Saitenlage notwendigerweise 11. Somit können sowohl der folgenden Zeichenketten strnameergeben sollten strresult="25":

strname="ph11go04325raa"
strname="325r"
strname="rgo04325raa"

Auch strname=ph12go04330raa"sollte nachgeben strresult="30".

Ich bin neu im Bash-Scripting und weiß nicht, wo ich anfangen soll, einen solchen String-Pattern-Matching durchzuführen. Hast du irgendwelche Vorschläge?

Antworten:


28

Sie können einen regulären Ausdruck in bash (3.0 oder höher) verwenden, um dies zu erreichen:

if [[ $strname =~ 3(.+)r ]]; then
    strresult=${BASH_REMATCH[1]}
else
    echo "unable to parse string $strname"
fi

In bash werden Erfassungsgruppen aus einem regulären Ausdruck in das spezielle Array eingefügt BASH_REMATCH. Element 0 enthält die gesamte Übereinstimmung, und 1 enthält die Übereinstimmung für die erste Erfassungsgruppe.


10

In der Standardsyntax sh(würde also mit jeder Version bashoder jeder anderen POSIX-kompatiblen Shell funktionieren) würden Sie Folgendes tun:

case $strname in
  (*3*r*) 
    strresult=${strname#*3}
    strresult=${strresult%r*};;
  (*)
    printf >&2 '%s\n' "Unable to parse string $strname"
esac

Siehe auch die alte exprLösung, die auch auf 35 Jahre alten Unices funktioniert:

expr "x$strname" : 'x[^3]*3\(.*\)r'

Das alte Manko bei exprist, dass Sie, wenn die Übereinstimmung fehlschlägt, einen Nicht-Null-Beendigungsstatus (in Ordnung) erhalten, aber auch einen Nicht-Null-Beendigungsstatus, wenn die zurückgegebenen Zeichenfolgen in 0 aufgelöst werden (wie bei strname=zz300rzz).


Ich denke, Ihre Formulierung impliziert fälschlicherweise, dass dies nur mit älteren Versionen von bash möglich ist. Die Parametererweiterung ist in modernen Schalen natürlich immer noch ein guter Ansatz.
— Kojiro

1
@kojiro, ich verstehe, was du meinst. Die anfängliche Formulierung bestand darin, die Antwort von Jordan weiterzuverfolgen. Ich habe meine Antwort aktualisiert.
— Stéphane Chazelas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.