Предполагая, что каждый раздел начинается с текста 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
Ваш синтаксис ошибочен, так как вы не можете просто сравнить стандартную ошибку какой-либо ранее выполненной команды с ==
.
Одно из предложений состоит в том, чтобы сохранить поток ошибок в файл, а затем проанализировать его:
#!/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
Вы можете направить 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 |... } >&3
fd жонглирования.