Как я могу пропустить первую и последнюю строку при использовании grep?

Я использую grep для поиска любых файлов, содержащих слово «привет» в текущем каталоге:

grep -l 'hello' *

Учитывая эти файлы:

тест1

hello
hi
how are you
stuff

тест2

welcome
hello
etc

тест3

hey
there
hello

Результат:

test1
test2
test3

Однако я хочу найти в этих файлах слово «привет», но пропустить первую и последнюю строки, поэтому мой вывод:

test2

Я знаю, что могу использовать следующую команду, чтобы игнорировать первую и последнюю строки:

sed '1d;$d' *

Но есть ли способ использовать это с grep, чтобы он игнорировал первую и последнюю строку каждого файла? Если нет, то как именно я могу использовать grep, чтобы пропустить первую и последнюю строку каждого файла?

вы хотите пропустить первую/последнюю строки каждого входного файла? или вы хотите пропустить первую/последнюю строки результирующего выходного набора?

markp-fuso 19.01.2023 23:47
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
105
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Так:

for file in *; do sed '1d;$d' "$file" | grep -q hello && echo "$file"; done

Эта задача больше подходит для awk.

awk 'FNR == 1 {p = ""; next}
     p ~ /hello/ {print FILENAME; nextfile}
     {p = $0}' test*

test2

Нет необходимости зацикливаться и вызывать внешние утилиты sed, grep несколько раз для каждой итерации.

Как это может работать в строке 2, если p еще не определен @anubhava?

Gilles Quénot 20.01.2023 06:07

@GillesQuenot: это работает для строки 2, потому что мы оцениваем условие p ~ /hello/, когда находимся в строке № 3.

anubhava 20.01.2023 07:53

Не понимаю, p ~ /hello/ включен $0 по умолчанию в строке № 3, насколько мне известно.

Gilles Quénot 20.01.2023 09:19

Нет, не на $0. Сравнение проводится с переменной p, которая была установлена ​​равной $0, когда мы обрабатывали предыдущую строку, то есть строку № 2.

anubhava 20.01.2023 09:55

Подлый! Хороший ответ ^^

Gilles Quénot 20.01.2023 15:43

Вы можете решить эту проблему, используя следующий код:

grep 'hello' test* | tail -n +2 | head -n -1

Это решает совершенно другую проблему — удаляет первую и последнюю найденные строки во всех файлах вместо того, чтобы не искать hello в первой и последней строке каждого файла.

Ed Morton 20.01.2023 02:28

Спасибо, @EdMorton, вы совершенно правы.

agarcias 20.01.2023 08:24

предполагая, что файлы меньше 500 MB или около того каждый, просто сделайте все за 1 выстрел:

 for __ in testfile_7000*txt; do

     echo "\n $__\n\n$( gcat -b "$__" |
                        gcat -n       )\n"
 done

 echo " searching for \"hello\" .....\n\n$(

    find . -maxdepth 1 -type f -name "testfile_7000*txt" -print0 |

    xargs -0 mawk 'BEGIN { OFS = FS = RS; RS = "^$"
                         _ = "" 
             } $!NF = $+($!_=$(NF-(_==$NF))=_)~"hello" ? FILENAME :_' | gcat -n )\n"  

 testfile_7000001.txt

     1       1  000hello
     2  
     3       2  testhello
     4       3   4355345


 testfile_7000002.txt

     1       1  000hell0
     2       2  testhllo
     3       3  84355345hello

 searching for "hello" .....

     1  ./testfile_7000001.txt
  • 2-я строка 1-го файла - пустая строка ""

Это может сработать для вас (GNU sed):

sed -sn '1d;$d;/hello/{F;:a;n;ba}' test*

Отключите неявную печать и обрабатывайте каждый файл отдельно.

Удалите первую и последнюю строки.

Вывести имя файла и выйти, если найдено совпадение для hello.

Альтернатива:

parallel -k 'tail -n+2 {} | head -n-1 | grep -qm1 hello && echo {}' ::: test*

или:

parallel -kq sed -n '1d;$d;/hello/{F;q}' {} ::: test*

Другие вопросы по теме