LINUX.ORG.RU

Разделить stderr и stdout

 , , ,


0

3

На входе в stdin есть набор строк. Хотелось бы те из них, в которых есть слово «error» отправить в stderr, а остальные в stdout. Вроде бы должно быть просто, но никак не могу написать функцию на шелле, хотя кажется, я это уже делал и даже успешно. Может у grep или tee есть такой режим работы?

★★★★★

Читаем построчно, срём выхлоп по результатам грепа (или если еггог в начале строки можно обойтись башем) построчно. 3 строки на баше. Кажется это будет не эффективно, лучше исправить вашу поделку.

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

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

anonymous
()

Например, так

>&2 grep error
>&1 grep -v error
Yorween
()
Ответ на: комментарий от anonymous

Что-то пошло не так. Попытка номер 2, чуть исправленная

$cmd | tee >(>&2 grep $expr) | grep --invert-match $expr
anonymous
()
Ответ на: комментарий от anonymous

3 строки на баше

Да можно и одной строкой:

while read -r; do [[ $REPLY = *error* ]] && printf "%s\n" "$REPLY" >&2 || printf "%s\n" "$REPLY"; done

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

У него быстрее наверно — меньше тактов и памяти впустую, без вызова внешней команды.

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

А вот с echo домашнее задание напечатать строку «-n» Хорош. Не знал, но подозревал о такой подставе, когда узнал что у echo есть опции командной строки.

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

Кривой markdown, цитата должна разделяться дополнительной пустой строкой.

А вот с echo домашнее задание напечатать строку «-n»

Хорош. Не знал, но подозревал о такой подставе, когда узнал что у echo есть опции командной строки.

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

а хотя это всё тупак, echo же тоже есть в баше, тогда man bash — там есть всё

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

Пойдёт. Теперь проверить на -e, -E и засунуть в тот однострочник.

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

Я написал на основе этого варианта свой чуть более сложный и с тестами он прекрасно работает, но на реальном тесте почему-то все ломает. Попробую написать минимальный тест для этого.

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

Это код на шелле, чего ты хочешь?

Я, пока писал пример, уже нашел из-за чего скрипт валится: в скрипте установлено set -e, а grep возвращает единицу, если нет совпадений, из-за чего скрипт останавливается.

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

Это код на шелле, чего ты хочешь? Это не код на шелле, это бесмысленное двойное дергание grep для каждой отдельной строки. Лучше посмотрел на вариант с шаблонами или встроенными в баш регулярками, либо tee >(grep $expr) | grep -v $expr

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

Привет кривой маркдаун

Это код на шелле, чего ты хочешь?

Это не код на шелле, это бесмысленное двойное дергание grep для каждой отдельной строки. Лучше посмотрел на вариант с шаблонами или встроенными в баш регулярками, либо tee >(grep $expr) | grep -v $expr

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

Я бы рад использовать here documents, но мне важна поддержка dash и busybox ash, так как это шеллы, на которых реально работает этот код. Мне больше всего нравится пример с sed, но я его недостаточно понимаю, чтобы изменить так, как мне нужно для конкретно этой задачи.

CYB3R ★★★★★
() автор топика
Ответ на: комментарий от ABW

Из этого примера я сделал такое: NINJA_STATUS="[ninja][%f/%t] " ninja -Cbuild | sed -n '/^\[ninja\]/!w /dev/stderr', теперь осталось только печатать не совпавшие строки на stdout, удаляя при этом первое вхождение [ninja] в них. Но моих познаний sed явно недостаточно.

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

поддержка dash и busybox ash

Поэтому ты используешь башизм $REPLY для read

Мне больше всего нравится пример с sed

Ты не знаешь используемые инструменты, ты их используешь, потому что нравится.

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

но мне важна поддержка dash и busybox ash,

Надо было сразу предупреждать.

filter() {
  local l n
  while read -r l; do
    n=${l#\[ninja\]}
    [ "x$l" != "x$n" ] && printf "%s\n" "$n" || printf "%s\n" "$l" >&2
  done
}

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

Скопировал пример с $REPLY отсюда, тестировал в busybox ash, всё работало. Если бы в dash отвалилось, переписал бы.

Ты не знаешь используемые инструменты, ты их используешь, потому что нравится.

Как будто что-то плохое. Знал бы, не создавал бы топик. А я создал, мне сразу предложили несколько разных решений одной задачи (за это и люблю ЛОР), я субъективно считаю решение с sed лучшим (нравится), но не могу его адаптировать, так как знаний не хватает (не знаю). Если ты думаешь, что я сейчас не читаю man sed, то ты ошибаешься.

CYB3R ★★★★★
() автор топика
Ответ на: комментарий от vodz

Спасибо! Работает, как надо.

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

пример с $REPLY отсюда, тестировал в busybox ash, всё работало. Если бы в dash отвалилось, переписал бы.

Это недокументированный башизм. В манах ash и dash этого нет.

субъективно считаю решение с sed лучшим (нравится)

Использовать редактор для перенаправления ввода-вывода - это должно именно нравиться, это не про знание.

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

А в коде ash есть, что объясняет, почему этот код у меня нормально работал. Однако всё равно спасибо тебе, что предостерёг, потому что я вообще не подозревал, что это башизм (я вообще не знал про переменную $REPLY до вчерашнего вечера).

Использовать редактор для перенаправления ввода-вывода - это должно именно нравиться, это не про знание.

А почему бы и нет? Вызовов внешних программ минимум, кода минимум, это просто code golf.

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

А почему бы и нет? это просто code golf.

Из shell, которая умеет (и предназначена) перенаправлять ввод-вывод, ты дергаешь редактор для этого.[br] Я знаю хороший «редактор» для этого, точнее операционнуя систему, - это Emacs.

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

Я не особо переживаю по этому поводу, потому что это далеко не самая плохая часть конвейера. После этой функции у меня работают две другие (одна для stderr, другая для stdout): каждую строчку на входе функция добавляет в файл stderr.txt или stdout.txt, а на stdout печатает «x» или ".", чтобы можно было визуально отслеживать количество строк в обоих файлах, посмотрев на одну длинную строчку на терминале, а если интересен сам вывод, заглянуть в файл. Так вот это реализовано через FIFO из-за невозможности использования here documents.

CYB3R ★★★★★
() автор топика
cat /var/log/Xorg.0.log | awk ' { if ( $0 ~ /EE/ ) {  print "ERROR! " $0 > "/dev/stderr" } else print "FINE! " $0;  } '
Aber ★★★★★
()
Ответ на: комментарий от CYB3R

Насчет ниндзи. Он весь вывод переводит в stdout (нехорошая тулза, мусорит в stdout). NINJA_STATUS тебя не спасет, так как не все свои выводимые строки форматирует в соответствии с этой переменной. Как пример

[ninja][1/1] gcc -c error.c -o error
FAILED: error
gcc -c error.c -o error
error.c:1:1: error: ...

Здесь строка FAILED: error выведено нинзей, никак не помечена.

Твоя задача должна решаться уровнем выше, в ninja.build в правилах rule, или враппером, который пишет лог в спец файл/пайп.

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

Там выше я давал ссылку на багтрекер ninja, где кто-то из разработчиков и посоветовал делать то, что я делаю. Ну или второй вариант – патчить ninja (ссылку я оставлял там же в багтрекере).

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

Там выше я давал ссылку на багтрекер ninja

Прочитал уже по диагонали. Там тебе ничего путного не ответили. Потому что твоя задача не решается этой переменной и патчить придется очень много. Хотя можно похакать src/line_printer.cc, чтоб он принудительно пихал метку в начало строки, но там тоже не все так просто из оптимизаций ввода-вывода. И надеяться, что в обход него ничего не выводится.

Решать надо выше, в генераторе ninja файлов (в cmake или что там используется).

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

Вряд ли это решается на стороне генератора.

Текущий нинзя не может решить эту проблему.

Вот тут (https://github.com/dendy/ninja/commit/2cc17a5626fee82617b032e20c7eb8124d80f837) проблему решают радикально патчем на ninja.

Сама поставленная задача правильная. Остальное (реализация, возможность кросплатформенной реализации и тд и тп) оценивать лень.

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