Я использую 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, чтобы пропустить первую и последнюю строку каждого файла?





Так:
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?
@GillesQuenot: это работает для строки 2, потому что мы оцениваем условие p ~ /hello/, когда находимся в строке № 3.
Не понимаю, p ~ /hello/ включен $0 по умолчанию в строке № 3, насколько мне известно.
Нет, не на $0. Сравнение проводится с переменной p, которая была установлена равной $0, когда мы обрабатывали предыдущую строку, то есть строку № 2.
Подлый! Хороший ответ ^^
Вы можете решить эту проблему, используя следующий код:
grep 'hello' test* | tail -n +2 | head -n -1
Это решает совершенно другую проблему — удаляет первую и последнюю найденные строки во всех файлах вместо того, чтобы не искать hello в первой и последней строке каждого файла.
Спасибо, @EdMorton, вы совершенно правы.
предполагая, что файлы меньше 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
""Это может сработать для вас (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*
вы хотите пропустить первую/последнюю строки каждого входного файла? или вы хотите пропустить первую/последнюю строки результирующего выходного набора?