Linux ищет строку только в заданном наборе файлов

Рецепт Жиля великолепен, но он не подходит для моих коммутаторов huawei 5720

но он работает после небольшой модификации

ssh-keygen -e -m pem -f ~/.ssh/id_rsa.pub | \
egrep -v  "BEGIN|END" | base64 -d | \
od -t x1 -An -w4 | tr 'a-f' 'A-F' | tr -d ' ' | fmt -w 72
1
13.12.2020, 21:30
3 ответа

Я предполагаю, что вы исправили окончания строк в стиле -DOS, как обсуждалось в комментариях, и что searchFiles.txtна самом деле не содержит пустых строк.

Тест -nameиз findиспользует только один шаблон имени файла. Шаблоны могут содержать символы оболочки, но они должны быть защищены от преждевременного создания имени файла оболочкой. Вы можете объединить несколько таких тестов с помощью логического ИЛИ, используя -o, но вы должны быть осторожны с приоритетом операторов.

Если ваша оболочка поддерживает массивы, вы можете сделать это следующим образом: (Здесь я использую bash, но аналогичные процедуры должны быть возможны и в других оболочках):

files=( -false )
while IFS= read -r f || [ -n "$f" ]; do files+=( -o -name "*$f"); done < searchFiles.txt

Это должно привести к ${files[@]}расширению до чередования

-false -o -name *file.a.txt -o -name *file.b.txt -o -name *file.c.txt -o -name *file.d.txt -o -name *file.e.txt

, который вы затем можете использовать в своей команде find, например

find. \( "${files[@]}" \) -exec grep -Ho '[^ ]*_XYZ' {} +

(Я опустил фиктивный файл /dev/nullв пользу добавления опции -H). Если количество файлов в searchFiles.txtслишком велико, этот подход может дать сбой из-за ограничений ARG_MAX. Вы можете обойти это ограничение, разбив searchFiles.txtна несколько файлов меньшего размера.

0
18.03.2021, 22:43

Вы должны быть в состоянии все это с GNU awk, например:

find. -type f -print0 |
  gawk '
    step == 1 {files[$0]; next} # record file names in "files" array
    step == 2 {
      # determine which files to look into (added to ARGV array for
      # processing in step 3)
      if ($NF in files) ARGV[ARGC++] = $0; next
    }
    NF {
      # record all matches (here in fields matched by FPAT)
      $1 = $1 # force a rebuild of $0 joining fields with OFS
      matches[FILENAME] = matches[FILENAME] \
                          (matches[FILENAME] == "" ? "" : OFS) \
                          $0
    }
    END {
      for (file in matches)
        print file ": " matches[file]
    }' step=1 searchFiles.txt \
       step=2 RS='\0' FS=/ - \
       step=3 RS='\n' FPAT='[^ ]*_XYZ' OFS=';'

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

find. -type f -print0 |
  gawk '
    step == 1 {
      gsub(/[][^$*()+{}?\\.|]/, "\\\\&") # escape regexp operators
      regex = regex sep $0; sep = "|"
      next
    }
    step == 2 {
      # determine which files to look into (added to ARGV array for
      # processing in step 3)
      if ($NF ~ ("(" regex ")$")) ARGV[ARGC++] = $0; next
    }
    NF {
      # record all matches (here in fields matched by FPAT)
      $1 = $1 # force a rebuild of $0 joining fields with OFS
      matches[FILENAME] = matches[FILENAME] \
                          (matches[FILENAME] == "" ? "" : OFS) \
                          $0
    }
    END {
      for (file in matches)
        print file ": " matches[file]
    }' step=1 searchFiles.txt \
       step=2 RS='\0' FS=/ - \
       step=3 RS='\n' FPAT='[^ ]*_XYZ' OFS=';'

Если вам нужно запутать его, вы можете поместить его в одну строку:

find. -type f -print0|gawk '!s{gsub(/[][^$*()+{}?\\.|]/,"\\\\&");r=r p $0;p="|";next};s==2{if($NF~("("r")$"))ARGV[ARGC++]=$0;next};NF{$1=$1;m[FILENAME]=m[FILENAME](m[FILENAME]==""?"":OFS)$0};END{for(f in m)print f":"m[f]}' searchFiles.txt s=2 RS=\\0 FS=/ - s=3 RS=\\n FPAT='[^ ]*_XYZ' OFS=\;

Они не делают предположений о том, какие символы могут содержать имена и содержимое файлов, за исключением того, что они должны быть допустимыми символами в локали. Суффиксы не могут иметь символ новой строки, но это ограничение определяется форматом вашего searchFiles.txt.

2
18.03.2021, 22:43

Вы можете отфильтровать имена файлов в вашем каталоге с помощью grep -fчерез текстовый файл с именами, чтобы включить (разрешая частичное совпадение ). Затем сделайте массивный grepв эти файлы для шаблона поиска и, наконец, отформатируйте результат с помощью небольшого awk.

Использование GNUbash:

grep -Ff filenames.txt <(printf '%s\n' *) |
    xargs -d '\n' grep -oH '[^[:space:]]*_XYZ$' | awk -F: '
        {f[$1] = f[$1] ? f[$1] ";" $2 : $0}
        END {for (x in f) print f[x]}'

Некоторые предположения (не все ясны в вопросе):

  • Ваши имена файлов удобны, без новой строки, без двоеточий (для grepвывода ). Пробелы обрабатываются.
  • Там нет подкаталогов, соответствующих этому каталогу, иначе второй grepвыдаст сообщение, но вернет результаты.
  • Второй grepищет шаблон в конце строки. Вы можете изменить его, если хотите, чтобы конец слов совпадал.
  • -Hдля grepиспользуется для углового случая одного файла, для печати имен файлов в выводе (это значение по умолчанию, когда есть два или более файлов)
0
18.03.2021, 22:43

Теги

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