col='REVISION' \
perl -lne '
$. == 1 and /(?:^|\s)(?=$ENV{col}(?:\s|$))/g and $h=pos, next;
/^.{$h}/g; /\G(\S+)/ and print $1;
next;
' yourfile
col='REVISION' \
perl -lne '
$. == 1 and $h = index($_, $ENV{col}), next;
/^.{$h}/g; /\G(\S+)/ and print $1;
' yourfile
В первой строке мы вычисляем позицию REVISION
, используя index ()
, работающий с текущей строкой $ _
. Для всех оставшихся строк мы пропускаем
позиции посредством сопоставления /^.../g. Затем используйте привязку \ G
, чтобы начать сопоставление с того места, где мы остановились ранее, и возьмите лежащие вне пробела символы \ S +
.
Выполнение этого в терминале:
Ошибка -Ожидание ввода$ grep "index123"
Работает -Получает ввод от STDIN $ echo -e "line1\nline2\nindex123blah\n" | grep "index123"
index123blah
Второй работает, потому что мы представили входные данные для grep
для синтаксического анализа через STDIN. grep
принимает ввод либо из стандартного ввода, либо из файла. В вашем сценарии:
if [[ "$d"=="*.out" && grep "index123"]]; then exit 1; fi
Он также не анализируется, следовательно, он не работает.
Судя по вашему коду, вы хотите что-то вроде этого. Для начала вот некоторые примеры данных:
$ mkdir -p 1/2/{3..5}
$ echo "index123" > 1/2/3/blah.out
$ echo "index123" > 1/2/3/blip.out
$ echo "index" > 1/2/blip.out
$ echo "index" > 1/2/blah.out
И измененная форма вашего скрипта:
$ cat loopy.bash
#!/bin/bash
while IFS= read -r d; do
grep -l "index123" "$d" && exit 1
done < <(find. -type f -name "*.out")
Работа:
$./loopy.bash
./1/2/3/blah.out
Создает первый найденный файл со строкой index123
и завершает работу.
Я бы так не поступил. Использование цикла while
здесь таким образом не обязательно. Было бы лучше использовать архитектуру find.... | xargs...
или тип решения find... -exec
.
См. ответ @DopeGhoti для лучшего подхода к использованию find
с -exec
или xargs
.
Если вы просто хотите распечатать содержащее дерево каталогов, в котором находится соответствующий файл, вы можете использовать dirname
, чтобы сделать это следующим образом:
$ cat loopy2.bash
#!/bin/bash
while IFS= read -r d; do
grep -q "index123" "$d" && dirname "$d" && exit 1
done < <(find. -type f -name "*.out")
И запустить его:
$./loopy2.bash
./1/2/3
Вот ваша проблема:
if [[ "$d"=="*.out" && grep "index123"]];
Предположим, что d=foo.out
. Теперь мы фактически имеем:
if [[ grep "index123"]];
Итак, вы пытаетесь указать grep
искать в стандартном вводе выражение /index123/
. Но на него не будет поступать никаких входных данных, так что он (будет казаться )зависшим, ожидая ввода. Однако он даже не зайдет так далеко, потому что if [[ grep "index123" ]]
на первый взгляд является недопустимым синтаксисом. Вместо этого вы хотите if grep "index123"
. Но опять же --, это будет просто ждать стандартного ввода.
Похоже, вы хотите вернуть из find
файлы с именем *.out
, которые содержат текст index123
. Так что попробуй это:
find. -prune -type d -name \*.out -print0 | xargs -0 grep -l 'index123'
Однако это find
утверждение довольно запутанно. Зачем find
все, а затем обрезать каталоги, когда мы могли бы просто искать нужные нам файлы?
find. -type f -name \*.out -print0 | xargs -0 grep -l 'index123'
Теперь вы увидите все файлы, содержащие искомый текст.
Нам даже не нужно выносить xargs
на стол, так как find
может вызвать grep
сам по себе:
find. -type f -name \*.out -exec grep -l 'index123' "{}" \;
Поиск всех *.out
файлов, содержащих строку index123
в текущем каталоге:
grep -lF 'index123'./*.out
Если вы хотите сделать рекурсивное grep
для всех *.out
файлов независимо от того, где они находятся в текущем каталоге:
find. -type f -name '*.out' -exec grep -lF 'index123' {} +
Печать каталога, в котором была найдена строка:
find. -type f -name '*.out' -exec grep -qF 'index123' {} ';' -exec dirname {} ';'
Выход после первого найденного имени каталога (с использованием GNUfind
):
find. -type f -name '*.out' -exec grep -qF 'index123' {} ';' -exec dirname {} ';' -quit
В зависимости от того, для чего вы планируете использовать имя каталога, вы должны заменить -quit
другим -exec
для обработки каталога любым способом, который вам нужен, или комбинировать различные -exec
утилиты в сценарий оболочки, вызываемый из -exec
. Что вы не делаете, так это передаете имя каталога какой-либо другой команде, поскольку это, как правило, небезопасно, если вы не примете дополнительные меры предосторожности при разграничении имени пути (s )нулевыми символами.
Связанные: