У меня есть строка вроде: "thisissometext"
. Я хочу найти все текстовые файлы в данном каталоге (рекурсивно), которые связываются с этой строкой, или любые ее вариации с пробелами и / или символами новой строки в середине. Например, текстовый файл, содержащий "this is sometext"
или "this\n issometext"
, "this\n isso metext"
, должен отображаться в поиске. Как я могу это сделать?
С более новыми версиями GNU grep
(который имеет -z
опция), можно использовать этот лайнер:
find . -type f -exec grep -lz 'this[[:space:]]*is[[:space:]]*some[[:space:]]*text' {} +
Рассмотрение пробелов может произойти промежуточное слова только.
Если Вы просто хотите искать все файлы, рекурсивно начинающие с текущего каталога, Вам не нужно find
, можно просто использовать grep -r
(рекурсивный). find
может использоваться, чтобы быть выборочным на файлах, чтобы искать, например, выбрать файлы который каталог исключить. Так, просто:
grep -rlz 'this[[:space:]]*is[[:space:]]*some[[:space:]]*text' .
Основной прием здесь -z
, это будет рассматривать каждую строку входного потока, законченного в ASCII NUL вместо новой строки, в результате мы можем соответствовать новым строкам при помощи обычных методов.
[[:space:]]
шаблон класса символов указывает на любые пробельные символы включая пространство, вкладку, CR, LF и т.д. Так, мы можем использовать его для соответствия всем пробельным символам, которые могут прибыть промежуточные слова.
grep -l
распечатает только имена файлов что, имея любой из желаемых шаблонов. Если Вы хотите распечатать соответствия также, использовать -H
вместо -l
.
С другой стороны, если бы пробелы могут прибыть в какие-либо места, а не слова, это освободило бы его хороший взгляд:
grep -rlz
't[[:space:]]*h[[:space:]]*i[[:space:]]*s[[:space:]]*i[[:space:]]*\
s[[:space:]]*s[[:space:]]*o[[:space:]]*m[[:space:]]*e[[:space:]]*\
t[[:space:]]*e[[:space:]]*x[[:space:]]*t' .
С -P
Опция (PCRE) можно заменить [[:space:]]
с \s
(это выглядело бы намного более хорошим):
grep -rlzP 't\s*h\s*i\s*s\s*i\s*s\s*s\s*o\s*m\s*e\s*\
t\s*e\s*x\s*t' .
Используя предложение @steeldriver для получения sed
генерировать шаблон для нас было бы наилучшим вариантом:
grep -rlzP "$(sed 's/./\\s*&/2g' <<< "thisissometext")" .
Код ниже ищет каталог рекурсивно файлы, удаляет все случаи " "
и "\n"
. Если строка существует в оставшемся тексте, существует соответствие. Это подразумевает, что пробелы/новые строки могут быть на любом положении в строке в Вашем файле (файлах).
Если это найдет соответствие файлам, то они будут распечатаны в терминале, включая их пути, как:
/home/jacob/Bureaublad/testmap/test2.txt
/home/jacob/Bureaublad/testmap/Naamloze map 2/test1.txt
Попытка / кроме я встроил, чтобы препятствовать тому, чтобы сценарий повредился, если это сталкивается с нечитабельным файлом.
#!/usr/bin/env python3
import os
import sys
s = sys.argv[2]
for root, dirs, files in os.walk(sys.argv[1]):
for file in files:
file = root+"/"+file
try:
if s in open(file).read().replace(" ", "").replace("\n",""):
print(file)
except:
pass
find_string.py
Выполните его с каталогом и строкой как аргументы:
python3 /path/to/find_string.py <directory> <string_to_find>
Если или строка или каталог содержат пробелы, используйте кавычки:
python3 /path/to/find_string.py '<directory>' '<string_to_find>'
Сценарий, поскольку это - файлы находок со строкой, или с пробелами или с новыми строками в нем. Это может быть расширено с другими символами/строками (например, вкладки) в строке:
if s in open(file).read().replace(" ", "").replace("\n",""):
Вы могли использовать grep -i --recursive 'word1\|word2' *
, и awk '/word1/,/word2/'
может использоваться для контакта с новой строкой
Можно удалить весь пробел и grep это:
tr -d '[[:space:]]' < foo | grep thisissometext
Расширение:
find . -type f -exec bash -c 'for i; do tr -d "[[:space:]]" < "$i" | grep -q thisissometext && printf "%s\n" "$i"; done' _ {} +
Эти bash
команда, расширенная:
for i
do
tr -d "[[:space:]]" < "$i" |
grep -q thisissometext &&
printf "%s\n" "$i"
done
Это циклично выполняется по всем аргументам и использует вышеупомянутый тест.