GNU/Linux >> Znalost Linux >  >> Linux

Test shellu, zda řetězec více řádků obsahuje zadaný vzor na posledním řádku?

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 )).

Související:Možnost kontextové nabídky Nautilus pro vytvoření nového souboru?

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.


Linux
  1. Jak odstranit první/poslední „n“ řádky z výstupu příkazu v prostředí Shell?

  2. Jak mohu v prostředí Linux zpracovat každý řádek víceřádkového řetězce?

  3. Jak nahradit řetězec ve více souborech v příkazovém řádku linuxu

  1. Najít číslo řádku, které obsahuje vzor, ​​pomocí vlastního oddělovače regulárního výrazu?

  2. Nahradit řádky odpovídající vzoru řádky z jiného souboru v pořadí?

  3. Jak připojit více řádků k souboru?

  1. Odstranit řádek obsahující určitý řetězec a následující řádek?

  2. Jak napsat víceřádkový řetězec pomocí Bash s proměnnými?

  3. Jak zřetězit více řádků výstupu do jednoho řádku?