grep в txt-файле или файлах без расширения, требуется наличие нескольких строк в файле

Начиная с версии 4.14.0, xfwm не предлагает функции добавления кнопки «полноэкранного режима» в оформление окна. Даже если бы это было так, украшения окон исчезали в полноэкранном режиме, поэтому его нельзя было бы использовать для выключения режима. То же предостережение относится к решениям, использующим виджеты панели и даже всегда -на -верхних окнах наложения.

Если вы хотите, чтобы двунаправленный переключатель для полноэкранного режима был легко доступен с помощью одной мыши, лучшее, что вы могли бы сделать, это привязать к этому действию дополнительную кнопку мыши, если она есть на вашей мыши. Для этого вы можете использовать пару программ xbindkeys и wmctrl .

Сначала установите обе программы. Убедитесь, что xbindkeysнастроен на запуск при запуске сеанса (xfce4-session-settings, вкладка «Автозапуск приложения»; пакеты вашего дистрибутива могут настроить его автоматически при установке ). Затем введите следующее в~/.xbindkeysrc:

"wmctrl -r :ACTIVE: -b toggle,fullscreen"
m:0x0 + b:NNN

замена NNN номером, соответствующим кнопке мыши по вашему выбору. Если вы не знаете этот номер, вы можете узнать его, используяxev:запуск xev -event buttonв окне терминала, нажмите эту кнопку, наведя курсор на окно xevи прочитайте номер из появившегося сообщения.

Если вас не слишком заботит отключение полноэкранного режима, вы можете просто создать панель запуска, которая запускает упомянутую выше команду wmctrl.

-2
06.02.2021, 09:57
3 ответа

Обновлено для измененного вопроса:

find directory -type f \( -name '*.txt' -o ! -name '*.*' \) \
    -exec grep -q -F -e 'string 1' {} \; \
    -exec grep -q -F -e 'string 2' {} \; \
    -exec grep -q -F -e 'string 3' {} \; \
    -print

При этом в каталоге с именем directoryвыполняется рекурсивный поиск обычных файлов с суффиксом имени файла .txtи обычных файлов без точки в имени. Когда такой файл найден, grepиспользуется способом, аналогичным тому, что я ранее описал (см. ниже ), чтобы выяснить, присутствуют ли в файле все три строки.

Если строки найдены, то печатается путь к файлу.

В качестве альтернативы, используя код из моей первой части этого ответа (снизу):

find directory -type f \( -name '*.txt' -o ! -name '*.*' \) -exec sh -c '
    for pathname do
        if  grep -q -F -e "string 1" "$pathname" &&
            grep -q -F -e "string 2" "$pathname" &&
            grep -q -F -e "string 3" "$pathname"
        then
            printf "All were found in \"%s\"\n" "$pathname"
        fi
    done' sh {} +

См. также:


Старый ответ до изменения вопроса:

Имя файла не имеет значения, поскольку Unix не определяет тип файла по имени файла.

Чтобы проверить, присутствует ли строка в каком-либо файле с именем file,можно сделать

if grep -q -F -e 'some string' file; then
    echo 'The string is present'
else
    echo 'The string is not present'
fi

Параметры, используемые с grepздесь:

  • -q:Это делает grepтихим, а также завершает его, как только шаблон совпадет. Вместо извлечения строки (s ), где шаблон совпадает, он завершается со статусом выхода, отражающим, было ли найдено совпадение или нет. Этот статус выхода я использую в операторе ifвыше.
  • -F:Это заставляет grepрассматривать шаблон как строку, а не как регулярное выражение. Это позволяет проверить, встречаются ли в тексте такие строки, как a * [in the] sky, без экранирования специальных символов в нем.
  • -e:Это заставляет grepрассматривать следующий аргумент как шаблон для сопоставления. Это позволяет использовать шаблон, начинающийся с -, не считая grepпараметром командной строки.

Чтобы проверить несколько строк, добавьте дополнительные grepтесты, подобные этому:

if  grep -q -F -e 'string 1' file &&
    grep -q -F -e 'string 2' file &&
    grep -q -F -e 'string 3' file
then
    echo 'All three string were found in the file'
else
    echo 'One or more string was not found in the file'
fi

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

strings=( 'string 1' 'string 2' 'string 3' )

found=true
for string in "${strings[@]}"; do
    if ! grep -q -F -e "$string" file; then
        found=false
        break
    fi
done

if "$found"; then
    echo 'All strings were found'
else
    echo 'Not all strings were found'
fi

Это перебирает строки, и если одна из них не найдена (обратите внимание на !, которая отрицает результат проверки grep), тогда переменная foundустанавливается в falseи цикл завершается (нам не нужно проверять дальнейшие строки ).

Затем мы проверяем, является ли $foundtrueили false, и действуем в соответствии с результатом этого теста.

Приведенный выше шелл-код переписан для/bin/sh(без именованных массивов):

set -- 'string 1' 'string 2' 'string 3'

found=true
for string do
    if ! grep -q -F -e "$string" file; then
        found=false
        break
    fi
done

if "$found"; then
    echo 'All strings were found'
else
    echo 'Not all strings were found'
fi
1
18.03.2021, 22:32

Отредактировано ниже для обновленного вопроса вы можете найти 2 шаблона, используя опцию -e. Файлы, которые вы просматриваете, не должны иметь расширения, просто используйте подстановочный знак, чтобы ваше утверждение выглядело примерно так

grep -e "word1" -e "word 2"  /your/folder/*

или таким образом для четных 3 строк в файлах, содержащих слово "txt"

 grep 'word1\|word2\|word3'  /your/folder/*txt*

Попробуйте, чтобы увидеть, что получится

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

grep "word 1"  /your/folder/* | grep "word 2"

Это передаст результаты первого grep другому с другой строкой. или выполните следующие действия

grep -e 'word1.*word2\|word2.*word1'  /your/folder/*

поэтому он будет искать сначала слово1, а затем слово2 или наоборот

-2
18.03.2021, 22:32

Поиск нескольких строк — это задача awk, а не grep:

find directory -type f \( -name '*.txt' -o ! -name '*.*' \) \
    -exec awk '
              index($0,"string 1"){x=1}
              index($0,"string 2"){y=1}
              index($0,"string 3"){z=1}
              x && y && z { f=1; exit }
              END { exit !f }
              ' {} \; \
    -print

Обратите внимание, что в приведенном выше примере awk вызывается только один раз для каждого входного файла, а не один раз для каждой строки для каждого входного файла. Также тривиально написать скрипт для поиска любого количества строк вместо жесткого -кодирования их построчно и при этом просто вызывать awk один раз для каждого файла, например.:

find directory -type f \( -name '*.txt' -o ! -name '*.*' \) \
    -exec awk '
              BEGIN {
                  totReqd = split("string 1 \
                                   string 2 \
                                   string 3", strings, /[[:space:]]+\n[[:space:]]+/)
              }
              {
                  for (idx in strings) {
                      if ( index($0,strings[idx]) ) {
                          totFound++
                          delete strings[idx]
                      }
                  }
              }
              totFound == totReqd { f=1; exit }
              END { exit !f }
              ' {} \; \
    -print

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

1
18.03.2021, 22:32

Теги

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