Hoe gebruik ik een regex in een shellscript?

Ik probeer een string te matchen met een regex in een shellscript.
Deze string is een parameter van het script ( $1 ) en het is een datum (MM/DD/YYYY)
De regex die ik probeer te gebruiken is:

^\d{2}[\/\-]\d{2}[\/\-]\d{4}$

Het lijkt te werken, ik heb het op verschillende regex-testwebsites geprobeerd.

Mijn shell-code is:

REGEX_DATE="^\d{2}[\/\-]\d{2}[\/\-]\d{4}$"
 
echo "$1" | grep -q $REGEX_DATE
echo $?

De “echo $?” geeft 1 terug, ongeacht de tekenreeks die ik in de parameter plaats.

Hebben jullie een idee?

Bedankt!


Antwoord 1, autoriteit 100%

Ik denk dat dit is wat je wilt:

REGEX_DATE='^\d{2}[/-]\d{2}[/-]\d{4}$'
echo "$1" | grep -P -q $REGEX_DATE
echo $?

Ik heb de schakeloptie -P gebruikt om perl regex te krijgen.


Antwoord 2, autoriteit 92%

Als aanvulling op de bestaande nuttige antwoorden:

Het gebruik van Bash’s eigen regex-matching-operator, =~, is in dit geval een sneller alternatief, aangezien u slechts een enkele waarde matcht die al is opgeslagen in een variabele:

set -- '12-34-5678' # set $1 to sample value
kREGEX_DATE='^[0-9]{2}[-/][0-9]{2}[-/][0-9]{4}$' # note use of [0-9] to avoid \d
[[ $1 =~ $kREGEX_DATE ]]
echo $? # 0 with the sample value, i.e., a successful match

Houd er echter rekening mee dat het voorbehoud bij het gebruik van smaakspecifieke regex-constructies zoals \devenzeer van toepassing is:
Hoewel =~ERE’s ondersteunt (uitgebreidereguliere expressies), ondersteunt het ook de specifieke extensie van het hostplatform– het is een zeldzaam geval dat het gedrag van Bash platform is -afhankelijk.

Om draagbaar te blijven (in de context van Bash), houdt u zich aan de POSIX ERE-specificatie.

Merk op dat je met =~zelfs capture groups(subexpressies tussen haakjes) kunt definiëren waarvan je later toegang kunt krijgen via Bash’s speciale ${BASH_REMATCH[@]}matrixvariabele.

Verdere opmerkingen:

  • $kREGEX_DATEwordt unquotedgebruikt, wat nodig is om de regex als zodanig te herkennen (geciteerde delen worden behandeld als literalsem>).

  • Hoewel niet altijd nodig, is het raadzaam om de regex eerst in een variabele op te slaan, omdat Bash problemen heeft met regex literalsdie \bevatten.

    • Bijvoorbeeld op Linux, waar \<wordt ondersteund om woordgrenzen te matchen, [[ 3 =~ \<3 ]] && echo yeswerkt niet, maar re='\<3'; [[ 3 =~ $re ]] && echo yesdoet.
  • Ik heb de variabelenaam REGEX_DATEgewijzigd in kREGEX_DATE(kgeeft een (conceptuele) constante aan), om ervoor te zorgen dat dat de naam geen naam in hoofdletters is, omdat variabele in hoofdletters namen moeten worden vermeden om conflicten met speciale omgevings- en shell-variabelen te voorkomen.


Antwoord 3, autoriteit 33%

het probleem is dat u regex-functies probeert te gebruiken die niet door grep worden ondersteund. namelijk, uw \dzal niet werken. gebruik in plaats daarvan dit:

REGEX_DATE="^[[:digit:]]{2}[-/][[:digit:]]{2}[-/][[:digit:]]{4}$"
echo "$1" | grep -qE "${REGEX_DATE}"
echo $?

je hebt de vlag -Enodig om EREom de stijl {#}te gebruiken.

Other episodes