grep пропускают n строки файла и только ищут после

Вот быстрая острота, которую можно ввести в терминале:

find . -name "*.wav" -print0 | while read -d $'\0' file; do neroAacEnc -2pass -q 1 -if "$file" -of "${file%wav}m4a"; done

Можно также использовать ffmpeg, как @slm предполагает,

find . -name "*.wav" -print0 | while read -d $'\0' file; do ffmpeg -i "$file" -c:a libfdk_aac -vbr 3 output.m4a "${file%wav}m4a"; done

Я не уверен, как neroAacEnc выдерживает сравнение с ffmpeg, но я знаю, что ffmpeg совершенствуется довольно популярный у многих пользователей Linux.


Объяснение

find программа, которая возвращает пути к файлам, которые соответствуют определенному свойству файла, в этом случае имя файла. Если бы все, что Вы хотели знать, было тем, какие .wav файлы находятся в подкаталогах Вашего текущего пути, то Вы сделали бы find . -name "*.wav". Обычно это производит каждый файл на новой строке. -print0 заставляет его разделить соответствия с нулевым символом вместо этого. Это допускает правильное обращение имен файлов с пробелами, когда мы передаем вывод следующим командам.

| символ известен как канал. Это говорит оболочке брать вывод команды слева и передавать его как вход к команде справа, в этом случае, read команда в while цикл.

read команда используется для взятия вывода find и присвойте его переменной, "файлу". Обычно это присвоило бы значения, чтобы "зарегистрировать" каждое слово за один раз, но -d $'\0'$ заставляет присвоения быть разграниченными нулевым символом (соответствие, как мы разграничили файлы в find при помощи -print0 флаг).

Причины циклов с условием продолжения read многократно присваивать значения "файлу" для каждого имени файла соответствия. do и done часть стандартного синтаксиса удара некоторое время цикл:

while <something is true>; do
    <run some commands>
done

В этом случае, наш "выполненный некоторая команда" также ffmpeg или neroAacEnc. В каждом из случаев, входной файл (т.е. $file) указан с переменной "файла", с которой мы присвоились read, и выходной файл (т.е. ${file%wav}w4a) управление этой переменной, которая позволяет нам указывать другое имя для вывода. Обычно $file или ${file} оценил бы к названию файла, сказал бы некоторый song.wav. % говорит для отключения от права на переменную любой последовательности, соответствующей символам [1] направо от % (т.е. "wav"). Так ${file%wav} оценил бы к некоторой песне., и затем "m4a" там, чтобы быть новым концом имени файла: некоторая песня m4a.


[1] Я говорю "символы" здесь для простоты. Последовательность направо от % могло быть регулярное выражение. Например, если мы сказали ${file%w*v} и переменная была некоторой песней w1234v, она также оценит к некоторой песне..

8
10.01.2015, 16:40
7 ответов

С помощью sed можно использовать диапазон и quit вход при одном завершении:

sed '/^182$/p;//,/^ABC$/!d;/^ABC$/!d;q'

Аналогично w/ GNU grep можно разделить вход между двумя grep s:

{ grep -nxF -m1 182; grep -nxF -m1 ABC; } <<\IN
123
XXY
214
ABC
182
558
ABC
856
ABC
IN

. ... который печатает ...

5:182
2:ABC

... что означает, что первый grep нашел -F ixed-строчный буквальный, -x целую строку 182 , совпадающую с 5 строками от начала его считывания, и вторая обнаружила, что аналогично набранная ABC совпадает с 2 строками от начала чтения - или с 2 строками после первого grep quit чтения на 5-й строке.

Из man grep:

-m NUM, --max-count=NUM
          Stop  reading  a  file  after  NUM  matching
          lines.   If the input is standard input from
          a regular file, and NUM matching  lines  are
          output, grep ensures that the standard input
          is  positioned  to  just  after   the   last
          matching  line before exiting, regardless of
          the  presence  of  trailing  context  lines.
          This  enables  a calling process to resume a
          search. 

Я использовал этот документ для воспроизводимой демонстрации, но вы, вероятно, должны это сделать:

{ grep ...; grep ...; } </path/to/log.file

Он также будет работать с другими оболочками составных командных конструкций, таких как:

for p in 182 ABC; do grep -nxFm1 "$p"; done </path/to/log.file
10
27.01.2020, 20:09

Изменение Perl, которое вы могли бы использовать:

perl -nle 'm/182/../ABC/ and print' file

... который печатает линии в диапазоне соответствия.

Если вы подаете файл, содержащийся более одного диапазона соответствия, вы можете ограничить вывод только на первый диапазон, изменяя разделитель / в ?

perl -nle 'm?182?..?ABC? and print'
1
27.01.2020, 20:09
> strace -c -f -e trace=fork,vfork,clone,execve,execl bash -c 'ls -ld /etc;sleep 1'
Process 15683 attached
drwxr-xr-x 1 root root 5540 10. Jan 02:08 /etc
Process 15684 attached
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         2           clone
  0.00    0.000000           0         3           execve
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                     5           total

> strace -c -f -e trace=fork,clone,execve bash -c '(foo=bar;ls -ld /etc);sleep 1'
Process 15730 attached
Process 15731 attached
drwxr-xr-x 1 root root 5540 10. Jan 02:08 /etc
Process 15732 attached
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         3           clone
  0.00    0.000000           0         3           execve
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                     6           total
-121--166960-

Использование GREP с использованием Perl-совместимых регулярными выражениями ( PCREGREP ):

pcregrep -Mo '182(.|\n)*?\KABC'

Опция -M Разрешить шаблон соответствовать Более одной строки, и \ k не включает в себя сопоставленные шаблон (до этой точки) в вывод. Вы можете удалить \ k , если вы хотите иметь весь регион в результате.

2
27.01.2020, 20:09
> awk '/^182$/ { startline=1; }; startline == 0 { next; }; /^ABC$/ { print "line " NR ": " $0; exit; }' file
line 7: ABC
2
27.01.2020, 20:09

приклеивая только grep и добавляя хвост и разрез , вы могли бы...

grep для номера линии первого совпадения 182:

grep -m 1 -n 182 /var/log/file |cut -f1 -d:

Используйте это, чтобы grep для всех ABC только после первой линии совпадения выше, используя tail's -n +K, чтобы вывести после линии K'th. Все вместе:

tail -n +$(grep -m 1 -n 182 /var/log/file |cut -f1 -d:) /var/log/file | grep ABC

Или добавьте -m 1 снова, чтобы найти только первое совпадение ABC

tail -n +$(grep -m 1 -n 182 /var/log/file|cut -f1 -d:) /var/log/file|grep -m 1 ABC

Ссылки:
man pages
https://stackoverflow. com/questions/6958841/use-grep-to-report-back-only-line-numbers

1
27.01.2020, 20:09

Другой вариант:

grep -n -A99999 "182" /var/log/file|grep -n -m1 "ABC"

Флаг -An greps n строк после совпадения, а 99999 - просто для того, чтобы мы ничего не пропустили. В файлах большего размера должно быть больше строк (проверьте с помощью "wc -l").

1
27.01.2020, 20:09

Оператор диапазона , может быть использован здесь:

< yourfile \
sed -e '
   /182/,/ABC/!d
   //!d;=;/ABC/q
' | sed -e 'N;s/\n/:/'

Оператор диапазона ... в тандеме с оператором match-only-once m?? может быть использован здесь в Perl

perl -lne 'm?182? .. m?ABC? and print "$.:$_" if /182/ || /ABC/' yourfile
0
27.01.2020, 20:09

Теги

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