PIPESTATUS игнорирует отрицание?
Я только что нашел следующие результаты в bash (версия 4.2.25(1)-релиз):
$ true; echo "${PIPESTATUS[@]}"
0
$ ! true; echo "${PIPESTATUS[@]}"
0
$ false; echo "${PIPESTATUS[@]}"
1
$ ! false; echo "${PIPESTATUS[@]}"
1
$ true && false; echo "${PIPESTATUS[@]}"
1
$ true && ! false; echo "${PIPESTATUS[@]}"
1
Так, $PIPESTATUS
кажется, игнорирует отрицания во всех случаях. Это известная проблема? Я не мог ничего найти об этом. Или это желаемое поведение? Если так, то в чем причина?
При использовании подоболочки все работает так, как я и ожидал:
$ (true && ! false); echo "${PIPESTATUS[@]}"
0
2 ответа
! a | b | c
интерпретируется как !{a | b | c;}
оболочкой, а не как {! a;} | b | c
,
Индивидуальные статусы выхода из команды хранятся в ${PIPESTATUS[@]}
,
$?
относится к состоянию выхода всей команды, включая !
,
Вы можете заставить (! a) | b | c
фактически порождая подоболочку. например
$ true; echo "${PIPESTATUS[@]}"
0
$ (! true); echo "${PIPESTATUS[@]}"
1
$ false; echo "${PIPESTATUS[@]}"
1
$ (! false); echo "${PIPESTATUS[@]}"
0
Я думаю, что это поведение предназначено и становится более ясным, если смотреть с полным конвейером:
a | b | c | d ; echo "${PIPESTATUS[@]}"
Это покажет статусы выхода процессов a
, b
, c
, а также d
,
Отрицания теперь применяются только к состоянию завершения всего конвейера:
! a | b | c | d ; echo "${PIPESTATUS[@]}"
Не допускается отрицание частей трубопровода:
a | ! b | c | d # Syntax error at "| !"
Благодаря такому подходу труба ассоциируется сильнее, чем отрицание (можно сказать, что это ! (a | b | c | d)
на уровне ассоциации), поэтому отрицание не влияет на результаты компонентов канала, поскольку отрицание применяется позже, после оценки конвейера.