Nowe posty

Autor Wątek: regexp - jak zanegować słowo? (a nie znak lub zakres znaków)  (Przeczytany 2277 razy)

addos2

  • Gość
Podczas korzystania z wyrażeń regularnych można zanegować jakiś znak lub zakres, np.
test.*[^a]abc
test.*[^aw]abc
test.*[^a-g]abc
Czy da się zanegować całe słowo? Próbowałem różnych kombinacji ale nie che mi to działać, np:

Wiadomości przychodzące od [^(Tomka|Bartka|Roberta)] a skierowane do [^(Tomka)] od ostatniej wizyty
Problem jest taki, że jakieś słowo może wystąpić kilka razy w jednej linii i nie można takiej linii potraktować opcją -v  (programu grep).
Gdy słowo będzie w odpowiednim miejscu to linia spełnia warunek, ale gdy będzie w innym miejscu to linia nie spełnia warunku.
Oczywiście cały czas mówimy o tekście w jednej linii.

Nie wiem czy dobrze to wyjaśniłem :)

Offline 1709

  • Users
  • Guru
  • *****
  • Wiadomości: 2561
  • 1709
    • Zobacz profil
Odp: regexp - jak zanegować słowo? (a nie znak lub zakres znaków)
« Odpowiedź #1 dnia: 2015-10-24, 19:42:47 »
Wiadomości przychodzące od [^(Tomka|Bartka|Roberta)] a skierowane do [^(Tomka)] od ostatniej wizyty
"Nie widze" tego jak by to miało działać jako skrypt,
ale jeśli (Tomka|Bartka|Roberta) były by w tablicy, albo w zmiennej, to można by było stworzyć nową tablicę albo nową zmienną z wyciętym danym słowem.
I jeszcze istnieje możliwość wycinanie słów, podmienianie...
Mógłbyś to dokładniej opisać oco chodzi / jak by to miało działać?
PS: Brak polskiej czcionki, nie jest to brak lenistwa, a jej brak w systemie i brak czasu na reczne poprawki.

addos2

  • Gość
Odp: regexp - jak zanegować słowo? (a nie znak lub zakres znaków)
« Odpowiedź #2 dnia: 2015-10-25, 11:32:37 »
Wyszukaj wszystkie wiadomości przychodzące z następującymi zastrzeżeniami:
a) nadawcą jest ktokolwiek oprócz: Tomka, Bartka, Roberta
b) odbiorcą jest ktokolwiek oprócz: Tomka

Offline ultr

  • Users
  • Guru
  • *****
  • Wiadomości: 1177
    • Zobacz profil
Odp: regexp - jak zanegować słowo? (a nie znak lub zakres znaków)
« Odpowiedź #3 dnia: 2015-10-25, 13:38:55 »
Cytuj
nie można takiej linii potraktować opcją -v  (programu grep).

Dlaczego nie?

grep -Ev '^Wiadomości przychodzące od (Tomka|Bartka|Roberta) a skierowane do (Tomka) od ostatniej wizyty$'
X: Wiadomości przychodzące od Tomka a skierowane do Tomka od ostatniej wizyty
X: Wiadomości przychodzące od Bartka a skierowane do Tomka od ostatniej wizyty
V: Wiadomości przychodzące od Ani a skierowane do Tomka od ostatniej wizyty
V: Wiadomości przychodzące od Bartka a skierowane do Oli od ostatniej wizyty

Nie jest to ogólne rozwiązanie problemu, ale może wystarczy.

Co do negacji słowa, to odpowiedź jest na google, które prowadzi tu:
http://stackoverflow.com/questions/406230/regular-expression-to-match-line-that-doesnt-contain-a-word
Ale jakoś nie działa to z grep-em :/

addos2

  • Gość
Odp: regexp - jak zanegować słowo? (a nie znak lub zakres znaków)
« Odpowiedź #4 dnia: 2015-10-25, 23:00:12 »
Bardziej interesował mnie odpowiednik tego: [^abc] ale nie dla liter a, b, c, tylko dla słowa "abc"

xavery

  • Gość
Odp: regexp - jak zanegować słowo? (a nie znak lub zakres znaków)
« Odpowiedź #5 dnia: 2015-10-30, 15:19:19 »
Sam problem jest pod względem akademickim ciekawy ale w wymiarze praktycznym lepiej to załatwić za pomocą negatywnych operatorów (!~) względnie negacji wyrażenia warunkowego. Jeśli z kolei piszesz o konkretnej pozycji w match'owamym stringu to może lepiej użyć narzędzi pozwalających na negowanie konkretnych składowych struktury tego stringu (np. awk).
Sama negacja całego wyrazu na poziomie wyrażeń regularnych wymaga zaprzęgnięcia zaawansowanych mechanizmów zwanych "negative lookbehind".
Z googla (sam bym tego przecież nie wymyślił:) ):


echo -e 'raz\ndwa\ntrzy' | grep -P '^((?!dwa).)*$'
raz
trzy


Generalnie jest to możliwe ale lepiej zastosować bardziej przejrzyste metody.