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.