Как найти все файлы, содержащие различные строки, из длинного списка комбинаций строк?

Вы можете заменить символы, используя формулу sed s/old_string/new_string/.

Из manpage:

sed - stream editor for filtering and transforming text

s/regexp/replacement/
              Attempt to match regexp against the pattern space.  If successful, replace that  portion  matched  with
              replacement.   The replacement may contain the special character & to refer to that portion of the pat‐
              tern space which matched, and the special escapes \1 through \9 to refer to the corresponding  matching
              sub-expressions in the regexp.

Если у вас есть набор символов для замены, то я рекомендую создать файл (например, replace.sed), содержащий определение замены следующим образом:

$ cat replace.sed
s/ă/a/g
s/â/a/g
s/î/i/g
s/ș/s/g
s/ț/t/g

А затем запуск можно выполнить так:

  • sed -f replace.sed new.php

    Который заменит символы, указанные в replace. sed новыми из old.php и выводятся в new.php

  • sed -i -f replace.sed file.php

    Которые заменяют file.php одновременно заменяя символы, указанные в replace.sed

    Из manpage:

    -i[SUFFIX], --in-place[=SUFFIX]
    
     редактировать файлы на месте (делает резервную копию, если указано SUFFIX)
    

Или вы можете определить одновременно в строке типа:

sed -e 's/ă/a/g' -e 's/â/a/g' -e 's/î/i/g' -e 's/ș/s/g' -e 's/ț/t/g'

Для выполнения этой операции для всех .php файлов, вы можете использовать что-то вроде:

  • find . -name "*.php" -exec sed -i '' -f replace.sed '{}' \;
  • for i in *.php; do sed -i '' -f replace.sed "$i"; done

Примечание: Используйте -maxdepth 1 с find для ограничения поиска *.php только в текущем каталоге. Посетите man sed для получения дополнительной информации.

6
13.04.2017, 15:37
4 ответа

Так как соглашениеp , похоже, отсутствует в вашей системе, обратите внимание на эту альтернативу, основанную на sed и awk, для применения grep и работы с шаблонами, считываемыми локальным файлом.

PS: Поскольку вы используете osx, я не уверен, поддерживает ли ваша версия awk указанное ниже использование.

awk может имитировать grep с помощью операции И для нескольких шаблонов в этом случае:
awk '/ pattern1 / && / pattern2 / && / pattern3 /'

Таким образом, вы можете преобразовать файл шаблона следующим образом:

$ cat ./tmp/d1.txt
"surveillance data" "surveillance technology" "cctv camera"
"social media" "surveillance techniques" "enforcement agencies"
"social control" "surveillance camera" "social security"
"surveillance data" "security guards" "social networking"
"surveillance mechanisms" "cctv surveillance" "contemporary surveillance"

На это:

$ sed 's/" "/\/ \&\& \//g; s/^"/\//g; s/"$/\//g' ./tmp/d1.txt
/surveillance data/ && /surveillance technology/ && /cctv camera/
/social media/ && /surveillance techniques/ && /enforcement agencies/
/social control/ && /surveillance camera/ && /social security/
/surveillance data/ && /security guards/ && /social networking/
/surveillance mechanisms/ && /cctv surveillance/ && /contemporary surveillance/

PS: Вы можете перенаправить вывод в другой файл, используя > другой файл в конце, или вы можете использовать параметр sed -i , чтобы сделать изменения на месте в том же файле шаблонов условий поиска.

Затем вам просто нужно загрузить в awk шаблоны в формате awk из этого файла шаблонов:

$ while IFS= read -r line;do awk "$line" *.txt;done<./tmp/d1.txt #d1.txt = my test pattern file

Вы также не можете преобразовать шаблоны в исходном файле шаблонов, применив sed в каждой строке этого исходного файла шаблонов следующим образом:

while IFS= read -r line;do 
  line=$(sed 's/" "/\/ \&\& \//g; s/^"/\//g; s/"$/\//g' <<<"$line")
  awk "$line" *.txt
done <./tmp/d1.txt

Или однострочно:

$ while IFS= read -r line;do line=$(sed 's/" "/\/ \&\& \//g; s/^"/\//g; s/"$/\//g' <<<"$line"); awk "$line" *.txt;done <./tmp/d1.txt

Приведенные выше команды возвращают правильные результаты И в моих тестовых файлах, которые выглядят следующим образом:

$ cat d2.txt
This guys over there have the required surveillance technology to do the job.
The other guys not only have efficient surveillance technology, but they also gather surveillance data by one cctv camera.

$ cat d3.txt
All surveillance data are locked.
All surveillance data are locked and guarded by security guards.
There are several surveillance mechanisms (i.e cctv surveillance, contemporary surveillance, etv)

Результаты:

$ while IFS= read -r line;do awk "$line" *.txt;done<./tmp/d1.txt
#or while IFS= read -r line;do line=$(sed 's/" "/\/ \&\& \//g; s/^"/\//g; s/"$/\//g' <<<"$line"); awk "$line" *.txt;done <./tmp/d1.txt
The other guys not only have efficient surveillance technology, but they also gather surveillance data by one cctv camera.
There are several surveillance mechanisms (i.e cctv surveillance, contemporary surveillance, etv)

Обновление:
Вышеупомянутое решение awk выводит содержимое совпадающих файлов txt.
Если вы хотите отображать имена файлов вместо содержимого, используйте следующий awk там, где это необходимо:

awk "$line""{print FILENAME}" *.txt
1
27.01.2020, 20:28

Проблема немного неудобная, но вы можете подойти к ней следующим образом:

while read one two three four five six
  do grep -lF "$one $two" *files* | xargs grep -lF "$three $four" | xargs grep -lF "$five $six"
done < patterns | sort -u

Это предполагает, что ваш Файл шаблона содержит ровно шесть слов в строке (три шаблона по два слова в каждом). Логические и реализованы путем объединения трех последовательных фильтров ( grep ). Обратите внимание, что это не особенно эффективно. Решение awk , вероятно, будет быстрее.

1
27.01.2020, 20:28

Это еще один подход, который, кажется, работает в моих тестах.

Я скопировал данные вашего строкового файла в файл с именем d1.txt и переместил его в отдельный каталог (т.е. tmp), чтобы в дальнейшем grep не соответствовал строковому файлу в том же файле (d1.txt).

Затем вставьте в этот файл строк (в моем случае d1.txt) точку с запятой между каждым поисковым запросом с помощью следующей команды: sed -i 's / "" / ";" / g' ./tmp /d1.txt

$ cat ./tmp/d1.txt
"surveillance data" "surveillance technology" "cctv camera"
"social media" "surveillance techniques" "enforcement agencies"
"social control" "surveillance camera" "social security"
"surveillance data" "security guards" "social networking"
"surveillance mechanisms" "cctv surveillance" "contemporary surveillance"
$ sed -i 's/" "/";"/g' ./tmp/d1.txt
$ cat ./tmp/d1.txt
"surveillance data";"surveillance technology";"cctv camera"
"social media";"surveillance techniques";"enforcement agencies"
"social control";"surveillance camera";"social security"
"surveillance data";"security guards";"social networking"
"surveillance mechanisms";"cctv surveillance";"contemporary surveillance"

Затем удалите двойные кавычки с помощью команды sed 's / "// g' ./tmp/d1.txt PS: Это может не быть действительно необходимым, но я удалил двойные кавычки для тестирования.

$ sed -i 's/"//g' ./tmp/d1.txt && cat ./tmp/d1.txt
surveillance data;surveillance technology;cctv camera
social media;surveillance techniques;enforcement agencies
social control;surveillance camera;social security
surveillance data;security guards;social networking
surveillance mechanisms;cctv surveillance;contemporary surveillance

Нет, вы можете использовать grep для всех файлов в текущем каталоге с помощью программы agreementp , которая разработана специально для обеспечения работы с несколькими шаблонами grep с операцией AND.

agreementp требует, чтобы несколько шаблонов были разделены точкой с запятой ; , чтобы их можно было вычислить как И.

В моих тестах я создал два образца файла с содержимым:

$ cat d2.txt
This guys over there have the required surveillance technology to do the job.

The other guys not only have efficient surveillance technology, but they also gather surveillance data by one cctv camera.

$ cat d3.txt
All surveillance data are locked.
All surveillance data are locked and guarded by security guards.
There are several surveillance mechanisms (i.e cctv surveillance, contemporary surveillance, etv)

Выполнение согласования в текущем каталоге возвращает правильные строки (с AND) и имена файлов:

$ while IFS= read -r line;do agrep "$line" *;done<./tmp/d1.txt
d2.txt: The other guys not only have efficient surveillance technology, but they also gather surveillance data by one cctv camera.
d3.txt: There are several surveillance mechanisms (i.e cctv surveillance, contemporary surveillance, etv)
1
27.01.2020, 20:28

Я бы использовал perl , что-то вроде:

perl -MFile::Find -MClone=clone -lne '
  # parse the strings.txt input, here looking for the sequences of
  # 0 or more characters (.*?) in between two " characters
  for (/"(.*?)"/g) {
    # @needle is an array of associative arrays whose keys
    # are the "strings" for each line.
    $needle[$n]{$_} = undef;
  }
  $n++;

  END{
    sub wanted {
      return unless -f; # only regular files
      my $needle_clone = clone(\@needle);
      if (open FILE, "<", $_) {
        LINE: while (<FILE>) {
          # read the file line by line
          for (my $i = 0; $i < $n; $i++) {
            for my $s (keys %{$needle_clone->[$i]}) {
              if (index($_, $s)>=0) {
                # if the string is found, we delete it from the associative
                # array.
                delete $needle_clone->[$i]{$s};
                unless (%{$needle_clone->[$i]}) {
                  # if the associative array is empty, that means we have
                  # found all the strings for that $i, that means we can
                  # stop processing, and the file matches
                  print $File::Find::name;
                  last LINE;
                }
              }
            }
          }
        }
        close FILE;
      }
    }
    find(\&wanted, ".")
  }' /path/to/strings.txt

Это означает, что мы минимизируем количество поисков строк.

Здесь мы обрабатываем файлы построчно. Если файлы действительно достаточно маленькие, вы можете обрабатывать их как единое целое, что немного упростит его и может улучшить производительность.

Обратите внимание, что он ожидает, что файл списка будет в формате:

 "surveillance data" "surveillance technology" "cctv camera"
 "social media" "surveillance techniques" "enforcement agencies"
 "social control" "surveillance camera" "social security"
 "surveillance data" "security guards" "social networking"
 "surveillance mechanisms" "cctv surveillance" "contemporary surveillance"

с числом (не обязательно 3) строк в кавычках (с двойными кавычками) в каждой строке.Строки в кавычках не могут содержать сами символы двойных кавычек. Символ двойной кавычки не является частью искомого текста. То есть, если файл списка содержит:

"A" "B"
"1" "2" "3"

, который будет сообщать путь ко всем обычным файлам в текущем каталоге и ниже, которые содержат либо

  • , либо A и B
  • , либо (не исключая или ) все 1 , 2 и 3

где-либо в них.

2
27.01.2020, 20:28

Теги

Похожие вопросы