Игнорировать очень конкретное сообщение об ошибке в bash

Предполагая, что каждый раздел начинается с текста Millionaire, вы сможете сделать это с помощью vim/ex-либо в интерактивном режиме, либо в сценарии, например, так:

$ ex SashaMillionaire.md << 'EOF'
:g/^Millionaire$/+5,+8 sort
:1,$p
:q
EOF

Millionaire
123456788763237476
QUESTION|2402394827049882049
Who is the greatest Goddess in the world?
Саша
Валерия
Катя
Кристина
Саша
AuthorOfQuestion
Millionaire
459385734954395394
QUESTION|9845495845948594999
Where Sasha live?
Novgorod
Chistopol
Kazan
Novgorod
St. Petersburg
Another author
Millionaire
903034225025025568
QUESTION|ABC121980850540445C
Another question.
Katya
Chistopol
Katya
Kazan
Sasha
Unknown author

Чтобы изменить файл на месте -, замените оператор печати 1,$pнаw

ex SashaMillionaire.md << 'EOF'
:g/^Millionaire$/+5,+8 sort
:wq
EOF

или, если вы предпочитаете один вкладыш -вместо настоящего документа,

printf ':g/^Millionaire$/+5,+8 sort\nwq\n' | ex SashaMillionaire.md
2
16.08.2019, 10:20
2 ответа

Ваш синтаксис ошибочен, так как вы не можете просто сравнить стандартную ошибку какой-либо ранее выполненной команды с ==.

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

#!/bin/bash

if ! my-bin-file-i-run 2>error.log; then
    if ! grep -q -F 'name_to_handle_at' error.log; then
       echo 'some error message' >&2
       exit 1
    fi
fi

Это запустит команду и перенаправит стандартный поток ошибок в файл с именем error.log. Если команда завершается с ошибкой, grepиспользуется для поиска строки name_to_handle_atв файле журнала. Если это не может быть найдено, печатается сообщение об ошибке, и сценарий завершается с нулевым статусом выхода, отличным от -.

В любом другом случае сценарий завершается с нулевым статусом выхода.

Если вы хотите, чтобы файл error.logудалялся при завершении работы вашего скрипта, вы можете сделать это явно с помощью rm error.logв соответствующих местах,или с ловушкой EXIT:

#!/bin/bash

trap 'rm -f error.log' EXIT

if ! my-bin-file-i-run 2>error.log; then
    if ! grep -q -F 'name_to_handle_at' error.log; then
       echo 'some error message' >&2
       exit 1
    fi
fi
6
27.01.2020, 21:53

Вы можете направить stderr вашей программы в grep и использовать(bash -специфическую переменную )PIPESTATUS, чтобы различать 4 комбинации успешного/неудачного выполнения команды и команды, напечатанной/не напечатанной, это сообщение об ошибке:

{ your_command 2>&1 >&3 | grep your_error_message >/dev/null; } 3>&1
case ${PIPESTATUS[*]} in
0*) ;; # the command succeeded
*0) ;; # the command failed but printed the error message
esac

Пример:

# usage wrapper pattern cmd args...
wrapper(){
    msg=$1; shift
    { "$@" 2>&1 >&3 | grep "$msg" >/dev/null; } 3>&1
    case ${PIPESTATUS[*]} in
    0*|*0) return 0;;
    *) return "${PIPESTATUS[0]}";;
    esac
}

# usage test_cmd status error_message
test_cmd(){ status=$1; shift; echo >&2 "$@"; return "$status"; }

$ wrapper foo test_cmd 13 foo; echo $?
0
$ wrapper foo test_cmd 13 bar; echo $?
13

Примечания:

Не заменяйте grep >/dev/nullна grep -q; это приведет к выходу grep при первом совпадении и вызовет SIGPIPE для вашей команды.

Однако вы можете поставить ... | tee /dev/stderr |...между вашей командой и grep; это приведет к тому, что сообщения об ошибках будут переданы в grep и напечатаны в stderr.

Многие некачественные программы (, особенно сценарии Python ), выводят сообщения об ошибках в стандартный вывод вместо стандартного stderr; если это так, вы можете просто использовать

your_command 2>&1 |...

вместо всего этого { 2>&1 >&3 |... } >&3fd жонглирования.

0
27.01.2020, 21:53

Теги

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