Szukam sposobu wyszukiwania plików, w których istnieją dwa wystąpienia słów w tym samym pliku. Do tego momentu korzystałem z następujących funkcji:
find . -exec grep -l "FIND ME" {} \;
Problem, na który wpadam, polega na tym, że jeśli nie ma dokładnie jednej spacji między „ZNAJDŹ” a „ME”, wynik wyszukiwania nie daje pliku. Jak dostosować poprzedni ciąg wyszukiwania, w którym w pliku występują oba słowa „ZNAJDŹ” i „ME”, a nie „ZNAJDŹ”?
Korzystam z systemu AIX.
grep -E
/,egrep
które opisuje wszystkie wzorce, którymi jesteś zainteresowany (i+
zamiast tego,;
jeśli twoje wyszukiwanie ma wsparcie+
.Odpowiedzi:
Za pomocą narzędzi GNU:
Możesz zrobić standardowo:
Ale to uruchomiłoby dwa greps na plik. Aby uniknąć uruchamiania tylu
grep
sekund i nadal być przenośnym, jednocześnie pozwalając na dowolny znak w nazwie pliku, możesz:Chodzi o to, aby przekonwertować dane wyjściowe
find
na format odpowiedni dla xargs (który oczekuje spacji (SPC / TAB / NL i innych spacji z twojego regionu z pewnymi implementacjamixargs
) oddzielonej listy słów, w których pojedyncze, podwójne cudzysłowy i ukośniki odwrotne mogą unikaj pustych miejsc i siebie nawzajem).Zasadniczo nie można przetworzyć wyniku
find -print
, ponieważ oddziela on nazwy plików znakiem nowej linii i nie zmienia znaków nowego wiersza znajdujących się w nazwach plików. Na przykład, jeśli zobaczymy:Nie mamy sposobu, aby wiedzieć, czy jest to jeden plik wywoływany
b
w katalogu o nazwie,a<NL>.
czy to dwa plikia
ib
.Używając
.//.
, ponieważ//
nie może pojawić się inaczej w ścieżce pliku jako wyjściefind
(ponieważ nie ma czegoś takiego jak katalog z pustą nazwą i/
nie jest dozwolony w nazwie pliku), wiemy, że jeśli widzimy wiersz zawierający//
, to jest to pierwszy wiersz nowej nazwy pliku. Możemy więc użyć tegoawk
polecenia, aby uciec od wszystkich znaków nowego wiersza oprócz tych poprzedzających te wiersze.Jeśli weźmiemy powyższy przykład,
find
wynik byłby w pierwszym przypadku (jeden plik):Który awk ucieka do:
To
xargs
postrzega to jako jeden argument. A w drugim przypadku (dwa pliki):Co
awk
by pozostało bez zmian, więcxargs
widzimy dwa argumenty.źródło
find ... -print0
igrep --null
zamiast tego?grep --null
(aka -Z) jest używane w pierwszym, ale jest rozszerzeniem GNU.-print0
(inne rozszerzenie GNU) tutaj by nie pomogło..//.
znaczy, i zastanawiam się, jak mogę to zmienić, aby zaakceptować argument z wiersza poleceń, powiedzmy$1
?-print0
zfind
a-0
zxargs
?find -print0
Nigdzie nie używam w mojej odpowiedzi.Jeśli pliki znajdują się w jednym katalogu, a ich nazwa nie zawierają miejsca, tabulacjami,
*
,?
ani[
znaków i nie zaczynać-
ani.
będzie to uzyskać listę plików zawierających ME, następnie zawęzić, że aż do tych, które zawierają również ZNAJDŹ.źródło
grep -l CategoryLinearAxis `grep -l labelJsFunction *`
, szukając plików, które zawierają oba atrybuty. Co za doskonały sposób to zrobić. +1Z
awk
tobą możesz również uruchomić:Używa
cx
icy
do liczeniaFIND
odpowiednio pasujących liniiME
. WEND
bloku, jeśli oba liczniki> 0, drukujeFILENAME
.Byłoby to szybsze / bardziej wydajne dzięki
gnu awk
:źródło
Lub użyj
egrep -e
lub wgrep -E
ten sposób:find . -type f -exec egrep -le '(ME.*FIND|FIND.*ME)' {} \;
lub
find . -type f -exec grep -lE '(ME.*FIND|FIND.*ME)' {} +
Te
+
marki znaleźć (jeśli jest obsługiwany) dodać kilka plików (ścieżka) nazw jako argumenty do polecenia będącego-exec
ed. Oszczędza to procesy i jest o wiele szybsze niż w przypadku,\;
gdy wywołuje polecenie raz dla każdego znalezionego pliku.-type f
dopasowuje tylko pliki, aby uniknąć grepowania w katalogu.'(ME.*FIND|FIND.*ME)'
to wyrażenie regularne pasujące do dowolnej linii zawierającej „ME”, po której następuje „FIND” lub „FIND”, po której następuje „ME”. (pojedyncze cudzysłowy, aby zapobiec interpretacji znaków specjalnych przez powłokę).Dodaj a
-i
dogrep
polecenia, aby rozróżniać wielkość liter.Aby dopasować tylko linie, w których „ZNAJDŹ” znajduje się przed „ME”, użyj
'FIND.*ME'
.Aby wymagać spacji (1 lub więcej, ale nic więcej) między słowami:
'FIND +ME'
Aby zezwolić na spacje (0 lub więcej, ale nic więcej) między słowami:
'FIND *ME'
Kombinacje są nieograniczone z wyrażeniami regularnymi i pod warunkiem, że jesteś zainteresowany dopasowywaniem tylko w rzędzie na raz, egrep jest bardzo potężny.
źródło
find
w pytaniu.Patrząc na przyjętą odpowiedź, wydaje się bardziej złożona niż powinna być. Wersje GNU
find
igrep
ixargs
wsparcia nul struny. To tak proste, jak:Możesz zmodyfikować swoje
find
polecenie, aby filtrować do żądanych plików, i działa z nazwami plików zawierających dowolny znak; bez dodatkowej złożonoścised
analizy. Jeśli chcesz dalej przetwarzać pliki, dodaj kolejny--null
do ostatniegogrep
I jako funkcja:
Oczywiście skorzystaj z zaakceptowanej odpowiedzi, jeśli nie korzystasz z wersji GNU tych narzędzi.
źródło
--null
,--print0
,-0
Są wszystkie rozszerzenia GNU. Chociaż niektóre z nich znajdują się obecnie w innych implementacjach, wciąż nie są przenośne i nie są w standardzie POSIX ani Unix.