Chci zjistit, zda víceřádkový řetězec končí řádkem obsahujícím zadaný vzor.
Tento kód selhal, neodpovídá.
s=`echo hello && echo world && echo OK`
[[ "$s" =~ 'OK$' ]] && echo match
Přijatá odpověď:
V bash
3.2 nebo vyšší a pokud není povolena kompatibilita s 3.1 (s compat31
možnost nebo BASH_COMPAT=3.1
), cituje operátory regulárních výrazů (nejen s ). ale s kterýmkoli z
bash
operátory uvozovek ('...'
, "..."
, $'...'
, $"..."
)) odstraňuje jejich zvláštní význam.
[[ $var =~ 'OK$' ]]
shoduje se pouze v řetězcích, které obsahují OK$
doslova (to znamená $
odpovídá doslovnému $
)
[[ $var =~ OK$ ]]
shoduje se s řetězci, které končí OK
(to $
je operátor RE, který se shoduje na konci řetězce).
To platí také pro regulární výrazy uložené v proměnných nebo jako výsledek nějaké substituce.
[[ $var =~ $regexp ]] # $var matches $regexp
[[ $var =~ "$string" ]] # $var contains $string
Všimněte si, že to může být nepohodlné, protože existují některé znaky, které musíte uvozovat pro syntaxi shellu (jako mezery, <
, >
, &
, závorky, když se neshodují). Například pokud chcete najít shodu s .{3} <> [)}]&
regulární výraz (3 znaky následované znakem " <> "
, buď )
nebo }
a &
), potřebujete něco jako:
[[ $var =~ .{3}" <> "[})]& ]]
Pokud máte pochybnosti o tom, které znaky je třeba uvozovat, můžete vždy použít dočasnou proměnnou. To také znamená, že kód bude kompatibilní s bash31
, zsh
nebo ksh93
:
pattern='.{3} <> [})]&'
[[ $var =~ $pattern ]] # remember *not* to quote $pattern here
To je také jediný způsob (zkratka použití compat31
možnost (nebo BASH_COMPAT=3.1
)) můžete využít rozšířené operátory jiných než POSIX regulárních výrazů vašeho systému.
Například pro <
chcete-li být považováni za hranici slova, kterou je v mnoha motorech regulárních výrazů, potřebujete:
pattern='<word>'
[[ $var =~ $pattern ]]
Dělám:
[[ $var =~ <word> ]]
nebude fungovat jako bash
zachází s těmito jako operátory citování shellu a před předáním
<word>
je oddělte do knihovny regulárních výrazů.
Všimněte si, že v ksh93 je to mnohem horší, kde:
[[ $var =~ "x.*$" ]]
například bude odpovídat na whatever-xa*
ale ne whatever-xfoo
. Výše uvedená citace odstraňuje speciální význam pro *
, ale ne do .
ani $
.
zsh
chování je jednodušší:citace nemění význam operátorů regulárních výrazů tam (jako v bash31), což přispívá k předvídatelnějšímu chování (může také používat regulární výrazy PCRE místo ERE (s set -o rematchpcre
)).
yash
nemá [[...]]
konstrukt, ale jeho [
vestavěný má =~
operátor (také v zsh
). A samozřejmě [
protože jde o normální příkaz, citace nemohou ovlivnit způsob interpretace operátorů regulárních výrazů.
Všimněte si také, že přísně vzato, vaše $s
neobsahuje 3 řádky, ale 2 plné řádky, za nimiž následuje neukončený řádek. Obsahuje hellonworldnOK
. V OK$
rozšířený regulární výraz, $
operátor by se shodoval pouze na konci řetězce .
V řetězci o 3 celých řádcích , například hellonworldnOKn
(které byste nebyli schopni získat substitucí příkazů jako proužky substituce příkazů vše znaky na konci nového řádku), $
by odpovídalo za n
, takže OK$
neodpovídalo by tomu.
Pomocí zsh -o pcrematch
nicméně $
shoduje se jak na konci řetězce, tak i před novým řádkem na konci řetězce, pokud nějaký existuje, protože nepředává PCRE_DOLLAR_ENDONLY
příznak na pcre_compile
. To by mohlo být považováno za špatný nápad, protože proměnné v shellech obecně neobsahují znak nového řádku na konci, a když ano, obecně je chceme považovat za data.