Как получить от grep только первое совпадение?

Если вам не нужны никакие хитрости в отношении структуры даты, т. е. она всегда будет иметь форму ГГГГ/ММ/ДД или ГГГГ -ММ -ДД, вы можете обойтись довольно простой командой, которая просто исправит первую строку каждого файла во всем дереве каталогов.

find. -type f -exec sed -i '1 s:-:/:g' {} \;
  • sed -iредактирует файл в месте -, нет необходимости объединять и перемещать файлы.
  • '1...редактирует только первую строку каждого файла.
  • 's:-:/:g'заменяет каждый экземпляр " -" в строке на "/"

После этого вы сможете повторно -запустить исходный скрипт и рассортировать эти файлы по каталогам с правильными датами.

0
05.10.2020, 23:15
1 ответ

В GNUgrep(реализация, найденная на rhel ), построена с поддержкой PCRE:

ps -Ao pid= -o args= |
  grep -Pom1 '^\s*\K\d+(?= \Q/usr/ud/bin/udt PHANTOM PHA-WRM-EXPIRE\E)'

Где

  • -Pпереключается на Perl -как регулярные выражения (для \s, \K, \d, (?=...), \Q, \Eвсех perl-подобных расширений ).
  • -oуказывает grepвыводить только совпадающую часть
  • -m1указывает grepвыводить совпадения только для первой совпадающей строки.

(все 3 флага являются расширениями GNU, но GNU grepявляется реализацией grep, найденной на вашем RHEL ).

Вместо того, чтобы использовать ps -f, который печатает ряд полей, которые нам не нужны, мы выбираем только те, которые нам нужны(pidи args, суффикс =для удаления заголовков ), чтобы нам было легче сопоставить их в командной строке.

Здесь регулярное выражение ищет начальную(^)последовательность из 0 или более(*)пробельных символов (\s), после чего мы отмечаем начало совпадения (\K), за которым следует последовательность из 1 или более(+)цифры (\d), при условии, что за ними следуют((?=...)оператор просмотра вперед, не являющийся частью совпадения )пробелом, и те аргументы, которые мы хотим (заключать в кавычки с \Q... \E, чтобы сделать это легче заменить другими списками аргументов, которые могут содержать операторы регулярных выражений ).

Или просто используйтеpgrep:

pgrep -f '^/usr/ud/bin/udt PHANTOM PHA-WRM-EXPIRE' | head -n 1

Возвращает pid для первого процесса, чей список аргументов (, объединенный пробелами, )начинается с /usr/ud/bin/udt PHANTOM PHA-WRM-EXPIRE.

Обратите внимание, что процессы упорядочены по pid по умолчанию в выводе psили pgrep, а числа pid переносятся, когда достигают своего максимального значения, поэтому то, какое из них вы получите, будет более или менее случайным.

Вы можете добавить некоторые --sort start_timeили --sort -start_timeк ps, например, для сортировки по времени начала (или добавить -o/ -nдля самых старых / . ] новейший до pgrepи отбросьте | head -n 1), если вы хотите получить процесс, который был запущен раньше/позднее,не то, чтобы это гарантировало, что это будет тот, который выполнилudtпервым/последним, поскольку процессы могут и часто выполняют более одной команды за время своего существования.

Если, как предполагает ваш комментарий к вашему вопросу, вы хотите выбрать процессы на основе их текущего рабочего каталога, вы можете вместо этого использовать zshи выполнить:

pids=(
  /proc/<1->(e[$'[[ $REPLY/cwd -ef /tdata/PHANTOM &&
    $(<$REPLY/cmdline) = /usr/ud/bin/udt\0PHANTOM\0PHA-WRM-EXPIRE\0* ]]']:t)
)

Здесь ищем процессы с /tdata/PHANTOMв качестве рабочего каталога и с /usr/ud/bin/udt, PHANTOMи PHA-WRM-EXPIREв качестве первых трех аргументов.

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

2
18.03.2021, 22:59

Теги

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