GNU/Linux >> Znalost Linux >  >> Linux

Zachyťte skupiny pomocí Awk nebo Grep?

Chtěl bych opakovat každý nalezený vzor a mít přístup k různým skupinám zachycení uvnitř smyčky, možná pomocí grep nebo awk (Chtěl bych s nimi zůstat, pokud je to možné, abych se vyhnul tomu, abych se naučil 3., ale pokud to bude opravdu nutné, naučím se další!)

Dělá něco jako:

awk-or-grep -E '(blah(.*)hello=(.*))' sampletext | while read -r l; do 
    echo $0             #1st capture group
    echo $1             #2nd catpure group
    dosomethingwith $2  #3rd capture group
done

existují?

Ukázkový text:

blah12687hello=123
nothingthatmatches
blah3211hello=123456
blah15butnottheotherpattern

S výše zmíněnou smyčkou by měl výstup:

blah12687hello=123
12687
<it should run the command dosomethingwith 123>
blah3211hello=123456
3211
<it should run the command dosomethingwith 123456>

Přijatá odpověď:

bash Shell sám o sobě poskytuje způsob, jak zpracovat porovnávání regulárních výrazů se zachycenými skupinami podle potřeby.

=~ operátor v testovacím výrazu s dvojitými závorkami, [[ se srovnávacím řetězcem na levé straně operátoru a regulárním výrazem jako pravým operandem.

if [[ "$str" =~ $re ]]; then

Pokud výraz odpovídá řetězci, odpovídající část řetězce je uložena v BASH_REMATCH pole, které lze přepnout do smyčky pro přístup k jednotlivým zachyceným skupinám. Stav ukončení je pokud se regulární výraz shoduje, 1 pokud ne, a 2 pokud je výraz neplatný.

Pokud jde o váš příklad, za předpokladu, že máte vstupní řádky uložené v poli a slova blah a hello jsou pevné vzory

#!/usr/bin/env bash

exampleStr=('blah12687hello=123' 'nothingthatmatches' 'blah3211hello=123456' 'blah15butnottheotherpattern')

re='blah([[:digit:]]+)hello=([[:digit:]]+)'

for str in "${exampleStr[@]}"; do
    if [[ "$str" =~ $re ]]; then
       for group in "${BASH_REMATCH[@]}"; do
           printf "%s\n" "$group"
       done
    else
       printf "No match \n"
    fi
done

Jak můžete vidět ve výše uvedeném kódu, jakmile přiřadíme regulární výraz tak, aby byl pravdivý, můžeme opakovat BASH_REMATCH pole pro tisk každé zachycené skupiny. Celkový výstup skriptu by byl něco jako

blah12687hello=123     # Value of BASH_REMATCH[0]
12687                  # Value of BASH_REMATCH[1]
123                    # Value of BASH_REMATCH[2]
Regex not matches.
blah3211hello=123456
3211
123456
Regex not matches.

Jak můžete vidět BASH_REMATCH[0] vždy obsahuje tu část řetězce, která byla úspěšně porovnána s regulárním výrazem, a k jednotlivým zachyceným skupinám lze přistupovat z indexu 1 Kupředu. Můžete napsat vlastní logiku pro zpracování každé zachycené skupiny, což je to, co jste původně zamýšleli udělat.

Související:Který je nejpřenosnější ze sed, awk, perl a sh?

Máte-li zájem o čtení vstupu souboru, stačí použít while smyčka s přesměrováním vstupu na soubor, který má být zpracován

while IFS= read -r line; do
    if [[ "$line" =~ $re ]]; then
       for group in "${BASH_REMATCH[@]}"; do
           printf "%s\n" "$group"
       done
    else
       printf "No match \n"
    fi
done < inputFile.txt

Linux
  1. Grep s logickými operátory?

  2. Zachyťte pakety pomocí tcpdump

  3. grep:skupinové zachycení

  1. Sdílení doplňkových skupin s kontejnery Podman

  2. Spravujte skupiny uživatelů Linuxu

  3. Spravujte skupiny zabezpečení a pravidla

  1. Příkaz AWK v Linuxu s příklady

  2. Použití grep vs awk

  3. Jak grep ps výstup s hlavičkami