/ / Získanie zvláštnych výsledkov pri práci s "[]" v egrep aj keď "" (escape sequence) používaný v Linuxe - regex, grep

Získanie zvláštnych výsledkov pri práci s "[]" v egrep aj keď "" (escape sequence) používaný v Linuxe - regex, grep

Nedávno som narazil na situáciu, keď som robil nejakú domácu prácu s regulárnymi výrazmi.

s@ubuntu:~$ echo b | egrep []b]
b
s@ubuntu:~$ echo b | egrep [[b]
b
s@ubuntu:~$ echo b | egrep []b[]
b
s@ubuntu:~$ echo b | egrep [b[]
b
s@ubuntu:~$ echo b | egrep [[b]]
s@ubuntu:~$ echo b | egrep [b]]
s@ubuntu:~$ echo b | egrep [b]]
s@ubuntu:~$ echo b | egrep [b\]]
s@ubuntu:~$ echo b | egrep [[b]]

Prečo sa v posledných piatich prípadoch nezobrazuje "b"?

odpovede:

3 pre odpoveď č. 1

Dôvodom je to v osobitných pravidlách, ktoré sa uplatňujú vo vnútri výrazových zátvoriek:

Pravá štvorhranná konzola] musia byť umiestnené hneď po otvorení [ alebo [^ považovať za doslovné.

a

Únikový znak sa zaobchádza doslovne v triede chars [...]

Pri návyku sa na shell použije únikový znak pred prejdením výrazu na egrep, kvôli chýbajúcemu singlu "..." alebo dvojitých úvodzoviek "..." okolo regexu.

Jonathan Leffler to dobre vysvetlí pomocou príkladov, môžem len uviesť odkaz na pravidlá rozšírenia Posix v zátvorkách a pridať prehľad:

http://pubs.opengroup.org/onlinepubs/007904875/basedefs/xbd_chap09.html#tag_09_03_05

UPDATE

Rovnaké výrazy s citátmi:

# this matches "b]" or "]"
~$ echo b] | egrep "[b]]"
b]
~$ echo "]" | egrep "[b]]" # note the quotes prior and after the pipe
]

# the next one is equivalent to "[b]]"
# cause a double  inside chars class is redundant
~$ echo b] | egrep "[b\]]"
b]
~$ echo "]" | egrep "[b\]]"
]

# the last one matches "]" or "[]" or "b]"
~$ echo b] | egrep "[[b]]"
[b]
~$ echo [] | egrep "[[b]]"
[]
~$ echo "]" | egrep "[[b]]"
]
# without quotes in the echo section, the escape  is applied by the shell
# so egrep receive only a closing bracket "]" and nothing is printed out
~$ echo ] | egrep "[[b]]"

# If we remove instead the quotes from the egrep section
# the regex becomes equivalent to [[b]] so it now matches "[]" or "b]" and not "]" anymore
~$ echo "]" | egrep [[b]]
~$ echo "[]" | egrep [[b]]
[]
~$ echo "b]" | egrep [[b]]
b]

5 pre odpoveď № 2
  • egrep [[b]] - Vyzerá to b alebo [ nasleduje a ]; nenájdené.
  • egrep [b]] - Vyzerá to b nasleduje a ]; nenájdené.
  • egrep [b]] - Vyzerá to b nasleduje a ]; nenájdené. Spätné lomítko je vynechané škrupinou a nie je vidieť egrep.
  • egrep [b\]] - Vyzerá to b alebo spätné lomítko nasledované ]; nenájdené.
  • egrep [[b]] - Vyzerá to b alebo a [ nasledovaný ]; nenájdené. Spätné lomky sú vynechané škrupinou a nie sú viditeľné egrep.

Vo vnútri triedy znakov (začal [), prvý ] ukončí triedu, pokiaľ ] je prvý znak po [, alebo prvý znak po [^ pre negovanú triedu znakov. Poznač si to ] nie je regex metacharakter, pokiaľ nie je predchádzajúci [ čím sa stáva koncom triedy postáv. Tiež to nájdete $ nie je metaznačkou uprostred reťazca, ani ^ pokiaľ sa nezobrazí na začiatku, ani * ani + ani ? ak sa zobrazia ako prvé atď. Pozri POSIX Pravidelné výrazy pre podrobnú diskusiu - regulárne výrazy, s ktorými sa zaoberá egrep (teraz grep -E) sú "rozšírené regulárne výrazy".

Oheň sa predtým mieša s opačnými lomami egrep dostane šancu vidieť ich. Mali by ste priložiť svoj regex do jednoduchých úvodzoviek, aby sa zabránilo tomu, že shell zmení čo egrep vidí.

Môžete preukázať svoju analýzu zmenou toho, čo sa ozýva:

echo "[b]" | egrep [[b]]
echo "[b]" | egrep [b]]
echo "[b]" | egrep [b]]
echo "[b]" | egrep [b\]]
echo "[b]" | egrep [[b]]

Výsledkom je:

[b]
[b]
[b]
[b]
[b]

Na [ v týchto príkladoch (v zopakoval údajov) je prítomná z kozmetických dôvodov; mohol byť vynechaný a riadky budú prijaté.