Сawk
:
awk '{ for (i=2;i<=NF;i++) if ($i!="NA"){ print; break } }' file
Перебрать поля, начиная со второго поля, и вывести строку, если найдено поле, не содержащее NA
. Затем разорвите петлю.
Дело в том, что не существует длинного имени процесса .
Существует имя процесса(/proc/pid/comm
в Linux ), которое в Linux имеет длину до 15 байт, унаследовано от родителя и изменяется каждый раз, когда процесс выполняет системный вызов execve()
к первым 15 байтам. базового имени исполняемого файла (, но также может быть изменено на любое произвольное значение с помощью prctl()
или путем записи в этот файл comm
).
Вот что сообщает ps
без -f
или с -o comm
. И что соответствует pgrep
по умолчанию.
А вот список аргументов, процесс передал команде, которую он выполнил последней(/proc/pid/cmdline
в Linux ). По соглашению первым аргументом является базовое имя или путь к исполняемому файлу.
ps -f
или ps -o args
печатает конкатенацию с пробелами этих аргументов, а pgrep -f
соответствует полученной строке. Из-за этой конкатенации вы теряете информацию о том, где начинается и заканчивается каждый аргумент.
Но если вы можете предположить, что первый аргумент не содержит пробелов, вы все равно можете сопоставить процессы, первый аргумент которых содержит my_long_script_name.sh
с:
pgrep -f '^[^ ]*my_long_script_name\.sh'
(замените pgrep
на pkill
, если вы хотите убить соответствующие процессы ).
Для чего-то более надежного, если на Linux, с zsh
, вы могли бы сделать:
print -C1 /proc/<->(Ne[$'[[ ${"$(<$REPLY/cmdline)"%%\0*} = (*/|)my_long_script_name.sh ]]']:t)
То есть получить информацию напрямую из /proc/pid/cmdline
,где аргументы разделены $'\0'
и проверьте, что часть, ведущая к первому $'\0'
, равна my_long_script_name.sh
или заканчивается на /my_long_script_name.sh
.
Направьте на xargs kill
, если вы хотите убить соответствующие процессы.