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 ★★★★★
()
Ответ на: комментарий от gedisdone

Но о FreeBSD речь не идёт.

Ну так и о Linux у тебя в ОП ни слова. ^_~

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

Если не критично по скорости

И по потреблению памяти. Пресмыкающееся очень любит кушать!

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

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

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

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

ps aux

Вот тебе мой добрый совет: изучи опции форматирования вывода ps и ты удивишься насколько упростится разборка вывода.

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

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

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

anonymous
()

читай /proc/ напрямую

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

критично по скорости

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

поржал

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)
Ответ на: комментарий от gedisdone

Последняя колонка не учтёт аргументы команды.

ps aux | tr -s ' '| cut -d ' ' -f1,2,3,4,9,11-
vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)

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

А какая тащемта задача?

Ford_Focus ★★★★★
()
ps aux | sed -rn 'h;s/((\S+\s+){10}).*/\1/gm;s/\s+/;/g;x;s/((\S+\s+){10})(.+)/\3/g;H;x;s/\n//g;p'
i-rinat ★★★★★
()
$ 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
()

Забиваешь гвозди микроскопом и находишь после этого битые стёкла на полу? Ну бывает. Молоток взять не пробовал?

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

Продолжая извращения (осторожно, башизм для перла)

$ ps aux | perl -pne "$(printf "%s" s/ '(?<g'{1..10}'>[^ ]+) +' '(.*)/' '$'{1..10}';' '$11/g')"
anonymous
()

А мог бы просто достать всё нужное из /proc

Nastishka ★★★★★
()
ps aux | perl -lne 'print join ";", split /\s+/, $_, 11'
pru-mike ★★
()

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

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 ★★★
() автор топика

А зачем такая задача? Экспортировать в Excel и бухгалтерия будет считать тебе премию по количеству воркеров демона?

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

Не всё ок, просто в ps должен быть внутренний механизм фильтрации вывода как и во всех утилках которые выплёвывают тонны.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.