Как искать текст в сжатых файлах и получать только имена файлов

Первая задача состоит в том, чтобы извлечь уровень из той строки. С GNU grep (не встроил Linux или Cygwin), можно использовать -o опция. Часть, которую Вы хотите, является одной содержащей только цифры, и сопровождаемый a % знак. Если Вы не хотите извлекать % самостоятельно, Вам нужен дополнительный прием: утверждение предвидения нулевой ширины, которое соответствует только, только если это ничто не сопровождается %.

command1 -p=aaa -v=bbb -i=4 | grep -o -P '[0-9]+(?=%)'

Другая возможность состоит в том, чтобы использовать sed. Для извлечения части строки в sed используйте s команда, с regex, который соответствует целой строке (запускающийся с ^ и окончание $), с частью для сохранения в группе (\(…\)). Замените целую строку содержанием группы (групп) для хранения. В целом передайте -n опция выключить печать по умолчанию и поместить p модификатор для печати строк, где существует что-то для извлечения (здесь существует одна строка, таким образом, это не имеет значения). Посмотрите Возврат только часть строки после шаблона соответствия и Извлечения regex, соответствовавшего 'sed', не печатая окружающие символы для большего количества приемов sed.

command1 -p=aaa -v=bbb -i=4 | sed 's/^.*rate(\([0-9]*\)%).*$/\1/'

Более гибкий снова, чем sed, awk. Awk выполняет инструкции для каждой строки на маленьком императивном языке. Существует много способов извлечь уровень здесь; я выбираю вторые поля (поля разграничены пробелом по умолчанию), и удалите все символы в нем, которые не являются цифрой.

command1 -p=aaa -v=bbb -i=4 | awk '{gsub(/[^0-9]+/, "", $2); print $2}'

Следующий шаг, теперь, когда Вы извлекли уровень, должен передать его как аргумент command2. Инструмент для этого является командой susbtitution. Если Вы вставляете команду $(…) (долларовая круглая скобка), ее выводом заменяют в командную строку. Вывод команды разделяется на отдельные слова в каждом пробельном блоке, и каждое слово рассматривают как подстановочный шаблон; если Вы не хотите, чтобы это произошло, поместите двойные кавычки вокруг замены команды: "$(…)". С двойными кавычками вывод команды используется непосредственно в качестве единственного параметра (единственное преобразование состоит в том, что новые строки в конце вывода удалены).

command2 -t "$(command1 -p=aaa -v=bbb -i=4 |
               sed 's/^.*rate(\([0-9]*\)%).*$/\1/')"

2
23.10.2015, 19:13
3 ответа

Вы можете выполнять работу zgrep вручную. Поскольку вам нужны только имена файлов, используйте grep только для проверки наличия шаблона и распечатайте имя файла, если шаблон найден.

#!/bin/sh
pattern=$1; shift
PATH=`getconf PATH`:$PATH # needed on Solaris 10 and earlier
                          # to get a standard grep
export PATH
found=0
for x do
  if case "$x" in
      *.gz|*.[zZ]) <"$x" gzip -dc | grep -q -e "$pattern";;
      *) <"$x" grep -q -e "$pattern";; 
     esac
  then
    found=1
    printf '%s\n' "$x"
  fi
done
if [ $found -eq 0 ]; then exit 1; fi

Для запуска как:

that-script 'pattern' file1 file2.gz file3.Z file.*.gz ...

Несколько замечаний, относящихся к вашей работе с Solaris 10 (также применимо к более ранним версиям и в некоторых отношениях также и к Solaris 11).

  • в этих системах / bin / sh является оболочкой Борна в отличие от стандартного POSIX sh . У вас есть выбор: сменить челку на #! / usr / xpg4 / bin / sh - , чтобы получить стандартный sh , или ограничиться древним синтаксисом Борна, как здесь (так что нет $ (...) ], no case $ x in (x) ... ) (Solaris 11 теперь использует POSIX-совместимую оболочку для своего / bin / sh (ksh93)).
  • в этих системах zcat обрабатывает только файлы .Z , сжатые с помощью compress , как это было в былые времена. Для файлов .gz необходимо вызвать gzip .
  • По умолчанию вам не обязательно использовать стандартные утилиты. Например, значение по умолчанию grep в / usr / bin является устаревшим и не поддерживает стандартную опцию -q . Чтобы получить стандартные утилиты, вам необходимо обновить $ PATH , указав пути, по которым можно найти стандартные утилиты (как вывод getconf PATH ).

Если вы хотите отобразить и имя члена архива, и номер строки или содержимое, вам нужно получить данные строки из grep и имя члена из скрипта. Удалите параметр -q из вызова grep и выполните постобработку его содержимого.

#!/bin/ksh
pattern=$1; shift
export PATH="$(getconf PATH):$PATH" # needed on Solaris 10 and earlier
                                    # to get a standard grep
found=0
for x do
  case "$x" in
      *.gz|*.[zZ]) <"$x" gzip -dc | grep -n -e "$pattern";;
      *) <"$x" grep -n -e "$pattern";; 
  esac | {
    filename=$x awk '{print ENVIRON["filename"] ":" $0; found=1}
                     END {exit(!found)}' && found=1
  }
done
if [ $found -eq 0 ]; then exit 1; fi
3
27.01.2020, 21:56

Поскольку ваши файлы на самом деле являются файлом tar.gz, вам также необходимо их распаковать. Tar - это утилита архивирования, которая объединяет несколько файлов (в вашем случае только один) и изначально использовалась для резервного копирования данных на ленточные накопители.

Утилита tar изначально не сжимала контент, поэтому он обычно передавался через gzip или другие утилиты для сжатия ... если вы разархивируете tar.gz, вы все равно останетесь со слоем достижения tar, поэтому он не работает.

в наши дни gun tar будет архивировать и архивировать за вас одной командой, используя команду "z".

так что для того, чтобы вы могли делать то, что вы хотите, я думаю, вам нужно использовать tar, распаковать «x», распаковать «z» из целевого файла «f» и передать поток на стандартный вывод «O», а затем передать по конвейеру grep.Это должно выглядеть примерно так:

 tar -xzf mycompressedlogfile.tar.gz -O | grep -l "pattern"

Поскольку ваша версия tar не имеет -z, попробуйте передать вывод gzip через tar перед grep

 gzip -dc mycompressedlogfile.tar.gz | tar -xOf - | grep -l "pattern"

Но я не думаю, что версия tar для Solaris 10 поддерживает параметр «O» для потоковой передачи содержимого tar на стандартный вывод. :( Вероятно, вам придется проделать то же самое (без O, поэтому "tar -xf -") для каждого файла из рабочего каталога или каким-либо способом убедиться, что вы можете учитывать созданные файлы, выполните поиск содержимое, а затем удалите файл (ы). Извините, если вы не можете установить gnu-tar на машине Solaris.

Я предполагаю, что из выбранного ответа вы смогли выполнить поиск в потоке tar для шаблона (поскольку это не сжатый, я думаю, это имеет смысл) и разберемся оттуда .. :) хорошая сделка.

Рад, что вы получили ответ.

1
27.01.2020, 21:56

Вот другое решение:

#!/bin/bash
# Grab the pattern, just like grep
re="$1"; shift

# Loop across the remaining arguments, or stdin if none
test 0 -eq $# && set -- -
for file
do
    # Search through the file (compressed or otherwise)
    zcat -f "$file" | grep -q "$re" && echo "$file"
done

Вы должны скопировать это в файл и сделать этот файл исполняемым (chmod a+x {filename}, а затем использовать его аналогично zgrep:

mkdir -p ~/bin
export PATH="$HOME/bin:$PATH"  # Add the ~/bin directory to your PATH. Also add this line to your ~/.profile

cat > ~/bin/mygrep             # Paste the file at this point, hit Ctrl/D on a blank line to end. Or otherwise edit ~/bin/mygrep
chmod a+x ~/bin/mygrep         # Make it executable

mygrep 'hello.*world' a*       # Search for the RE 'hello.*world' in all files beginning with 'a'

Если вы обнаружите, что zcat -f или grep -q не распознаются, вы можете заменить их на следующие

( zcat "$file" 2>/dev/null || cat "$file" )    # zcat -f "$file"
grep "$re" 2>/dev/null                         # grep -q "$re"

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

( zcat "$file" 2>/dev/null || cat "$file" ) | grep "$re" 2>/dev/null && echo "$file"
1
27.01.2020, 21:56

Теги

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