LINUX.ORG.RU
ФорумAdmin

Адский разбор вывода ps aux регулярками

 , , ,


1

1

sed не распознаёт обратные ссылки больше 9. Таким образом, код

ps aux | sed -r 's/([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +(.*)/\1;\2;\3;\4;\5;\6;\7;\8;\9;\10;\11/g'
не работает так, как предполагалось. Последние колонки отображатся как USER0, USER1. Perl тоже не видит дальше девятой обратной ссылки. В итоге команда
ps aux | perl -ne 's/([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +(.*)/\1;\2;\3;\4;\5;\6;\7;\8;\9;\10;\11/g; print $_' 
просто ничего не выдаёт дальше девятой колонки.

Зато сработала команда

ps aux | perl -ne 'm/([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +(.*)/; print $1 . ";" . $2 . ";" . $3 . ";" . $4 . ";" . $5 . ";" . $6 . ";" . $7 . ";" . $8 . ";" . $9. ";" . $10 . ";" . $11 . "\n"' 

Я понимаю, что должны быть более лёгкие способы реализации, укажите, пожалуйста.

Это 3.14159-здец, чувак!

Я понимаю, что должны быть более лёгкие способы реализации, укажите, пожалуйста.

Ну вот у меня в FreeBSD для этого есть --libxo (и не только у ps(1)), который умеет выплёвывать в том числе в json (но пока не умеет в csv, с которым было бы ещё проще), для которого парсеров — хоть жопой жуй.

mord0d ★★★★★ ()

Тот случай, когда понимаешь, что третье утверждение из UNIX-Way:

Пишите программы, которые бы поддерживали текстовые потоки, поскольку это универсальный интерфейс».

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

А как было бы удобно, если бы ps мог отдавать объект или хотя бы просто структурку.

EXL ★★★★★ ()

Если не критично по скорости, то можно выбрать «ползающего» =)

import psutil

for proc in psutil.process_iter():
	try:
		pinfo = proc.as_dict(attrs=['pid', 'username', 'cpu_percent', 'name'])
		pinfo['cpu_percent'] = proc.cpu_percent(interval=1)
		print(pinfo)
		if pinfo['cpu_percent'] > 0:
			print('cpu=',pinfo['cpu_percent'])
	except psutil.NoSuchProcess:
		pass

Atlant ★★★★★ ()
Ответ на: комментарий от EXL

Понятии не имею, надо проверять
P.S. Предупреждаю: Это был ОООЧЕЕЕНЬ ТОРМОЗНУТЫЙ КОД =)
Не вздумай использовать в итоговой версии!

Atlant ★★★★★ ()
Последнее исправление: Atlant (всего исправлений: 1)
Ответ на: комментарий от EXL

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

Неучь кнопочная.

anonymous ()
Ответ на: комментарий от anonymous

Хорошо. Есть ps -eo "%p\t%C\t%y\t%x\t%U\t%c\t%a" . Вместо табуляций подставляется просто \t. Мне это как обходить? Только через printf -v format "%%p\t%%C\t%%y\t%%x\t%%U\t%%c\t%%a"; ps -eo "$format"? P.S.: А нет, ещё можно ps -eo "$(printf "%%p\t%%C\t%%y\t%%x\t%%U\t%%c\t%%a")" Это правильно?

gedisdone ★★★ ()
Последнее исправление: gedisdone (всего исправлений: 2)
$ ps aux | perl -pne 's/([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +(.*)/$1;$2;$3;$4;$5;$6;$7;$8;$9;$10;$11/'

Можно использовать именованные группы

$ ps aux | perl -pne 's/(?<uname>[^ ]+) +(?<pid>[^ ]+)/user=$+{uname};pid=$+{pid}/'

(написал, не проверив, вроде, не ошибся в закорючках, должно работать)

anonymous ()

Как ни странно, на баше всё довольно тривиально.

ps aux | while read user pid cpu mem vsz rss tty stat start time command; do printf "%s;%s;%s%s;%s;%s;%s;%s;%s;%s;%s\n" "$user" "$pid" "$cpu" "$mem" "$vsz" "$rss" "$tty" "$stat" "$start" "$time" "$command"; done

gedisdone ★★★ ()