Chciałbym znaleźć linie w plikach z wystąpieniem jakiegoś wzorca i brakiem innego wzorca. Na przykład muszę znaleźć wszystkie pliki / linie, w tym loom
oprócz tych z rozszerzeniem gloom
. Więc mogę znaleźć za loom
pomocą polecenia:
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
Teraz chcę wyszukiwać z loom
wyłączeniem gloom
. Jednak oba poniższe polecenia nie powiodły się:
grep -v 'gloom' -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
grep -n 'loom' -v 'gloom' ~/projects/**/trunk/src/**/*.@(h|cpp)
Co mam zrobić, żeby osiągnąć swój cel?
EDYCJA 1: Mam na myśli toloom
igloom
są sekwencje znaków (niekoniecznie słowa). Tak więc potrzebuję na przykładbloomberg
w danych wyjściowych polecenia i nie potrzebujęungloomy
.
EDYCJA 2: Jest próbka moich oczekiwań. W danych wyjściowych polecenia znajdują się oba poniższe wiersze:
Spojrzałem na ikony, które majaczyły przez zasłonę kadzidła.
Arty jest slooming w ponury dzień.
Oba poniższe wiersze nie są wyświetlane w danych wyjściowych polecenia:
To jest ponure, straszne - wspaniali łajdacy cloodsów.
W południowo-zachodniej części hali heigh pyntit
there is a loom in the gloom
- czy chciałbyś wydrukować ten wiersz? Po prostu próbuję zrozumieć, czy szukasz tylko linii, w których krosna występuje inaczej niż jako część mroku, lub jeśli naprawdę chcesz wykluczyć linie zawierające mrok, nawet jeśli krosno pojawia się samo w innym miejscu linii. Pomogłoby wysłanie przykładowych danych wejściowych i oczekiwanych wyników.How do I find lines containing the string "loom" where "loom" is not preceded by the letter "g"
? Gdybyś zamieścił przykładowe dane wejściowe i pożądane dane wyjściowe, bardzo by to pomogło. Odpowiedź na to pytanie zawarta jest w odpowiedziach poniżej.loom
bez poprzedzeniag
. (Przepraszam. Zacząłem komentować wczoraj, ale nigdy nie skończyłem. Przypadkowo ten komentarz został wysłany.)Odpowiedzi:
A może po prostu łańcuch grepsów?
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
źródło
bloomberg
w wyjściu polecenia i nie potrzebujęungloomy
. Jeśli pojedyncza linia zawierałaby „… a Bloomberg nie jest ponury co do perspektyw…”, wyeliminowałbyś tę linię, ale jest pożądana (ponieważ jeśli zawierabloomberg
).Inne rozwiązanie bez łączenia
grep
:egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
Między nawiasami wykluczasz znak
g
przed jakimkolwiek wystąpieniemloom
, chyba żeloom
jest to pierwszy znak wiersza.źródło
Trochę stary, ale no cóż ...
Rozwiązanie, które otrzymało najwięcej głosów, od @houbysoft nie zadziała, ponieważ wykluczy każdą linię z wyrażeniem „mrok”, nawet jeśli zawiera słowo „loom”. Zgodnie z oczekiwaniami OP, musimy uwzględnić linie z „krosnami”, nawet jeśli mają w sobie również „mrok”. Ta linia musi znajdować się na wyjściu „Arty zasługuje na mrok w ponurym dniu”, ale zostanie to wykluczone przez przykutego grepa, takiego jak
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
Zamiast tego przykład wyrażenia regularnego egrep z Bentoy13 działa lepiej
egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
ponieważ będzie zawierał dowolną linię zawierającą słowo „loom”, niezależnie od tego, czy zawiera on słowo „mrok”. Z drugiej strony, jeśli ma tylko mrok, nie będzie go zawierał, a jest to dokładnie zachowanie, którego chce OP.
źródło
Po prostu użyj awk, jest znacznie prostszy niż grep, jeśli chodzi o jasne wyrażanie warunków złożonych.
Jeśli chcesz pominąć wiersze zawierające oba
loom
igloom
:awk '/loom/ && !/gloom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)
lub jeśli chcesz je wydrukować:
awk '/(^|[^g])loom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)
a jeśli w rzeczywistości chcesz po prostu linie, w których
loom
pojawia się samo w sobie:awk '/\<loom\>/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)
źródło
abc
adef
ighi
w dowolnej kolejności. Teraz porównaj to zawk '/abc/ && /def/ && /ghi/'
. Zastanów się teraz, w jaki sposóbawk '/loom/ && !/gloom/'
w odpowiedziach na tej stronie zapisywany jest odpowiednik grep .condition { action }
składnią awks, ale wtedy jest to pestka dla każdego, kto ma jakiekolwiek doświadczenie w języku C lub innym języku bazującym na Algolu.grep -Hn --color
:awk '/loom/ && !/gloom/ { gsub(/loom/, color("1;31") "&" color(0)); print color(35) FILENAME color(36) ":" color(32) FNR color(36) ":" color(0) $0; }; function color(c) { return "\033[" c "m"; }'
-v
jest flagą „odwrócone dopasowanie”, więc potokowanie jest bardzo dobrym sposobem:grep "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)| grep -v "gloom"
źródło
/ * Może wyglądasz coś takiego?
grep -vn "gloom" `grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)`
BACKQUOTES są używane jak nawiasy kwadratowe dla poleceń, więc w tym przypadku, gdy
-l
włączone, kod w BACKQUOTES zwróci nazwy plików, a następnie z opcją -vn, aby zrobić to, co chciałeś: mieć nazwy plików, numery linii, a także rzeczywiste linie.UPDATE Lub z xargs
grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp) | xargs grep -vn "gloom"
Mam nadzieję, że to pomoże. * /
Proszę zignorować to, co napisałem powyżej, to bzdury.
grep -n "loom" `grep -l "loom" tt4.txt` | grep -v "gloom" #this part gets the filenames with "loom" #this part gets the lines with "loom" #this part gets the linenumber, #filename and actual line
źródło
Możesz użyć
grep -P
(perl regex) obsługiwanegonegative lookbehind
:grep -P '(?<!g)loom\b' ~/projects/**/trunk/src/**/*.@(h|cpp)
Dodałem
\b
dla granic słów.źródło
\([^g]\|^\)
działa. I to nie wyklucza wierszy zawierających obaloom
igloom
.not gloom
.bloomberg
w wyjściu polecenia i nie potrzebujęungloomy
. Zatem granice słów przynoszą efekt przeciwny do zamierzonego.grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
źródło
bloomberg
w wyjściu polecenia i nie potrzebujęungloomy
. Jeśli pojedyncza linia zawierałaby „… a Bloomberg nie jest ponury co do perspektyw…”, wyeliminowałbyś tę linię, ale jest pożądana (ponieważ jeśli zawierabloomberg
).Po prostu użyj!
grep -v
wiele razy.Treść pliku
[root@server]# cat file 1 2 3 4 5
Wyklucz linię lub dopasuj
[root@server]# cat file |grep -v 3 1 2 4 5
Wyklucz linię lub dopasuj wiele
[root@server]# cat file |grep -v 3 |grep -v 5 1 2 4
źródło
Pytanie: wyszukaj „loom” z wyłączeniem „mrok”.
Odpowiedź:
grep -w 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
źródło
bloomberg
w wyjściu polecenia i nie potrzebujęungloomy
. Nie sądzę, żeby-w
to było rozwiązanie tej zagadki.