Ответ 1
Просто отрицать возвращаемое значение.
! grep -P "STATUS: (?!Perfect)" recess.txt
Как я могу уменьшить следующие bash script?
grep -P "STATUS: (?!Perfect)" recess.txt && exit 1
exit 0
Кажется, что я могу сделать это с помощью одной команды, но у меня здесь всего 3.
Моя программа должна:
Ответ на награду распространяется на самый жесткий script. Спасибо!
Программа должна иметь статус выхода 0 для этого файла:
FILE: styles.css
STATUS: Perfect!
FILE: contour-styles.css
STATUS: Perfect!
Программа должна иметь статус выхода 1 (или ненулевой) для этого файла:
FILE: styles.css
STATUS: Perfect!
FILE: contour-styles.css
STATUS: Busted
FAILURES: 1 failure
Id should not be styled
1. #asdf
Просто отрицать возвращаемое значение.
! grep -P "STATUS: (?!Perfect)" recess.txt
Я наткнулся на это, требуя инструкции onlyif
для Puppet. Таким образом, Tgr bash solution не будет работать, и я не хотел бы расширять сложность, как в Christopher Ответ Нейлана.
В итоге я использовал версию, вдохновленную ответом Анри Шомэкера, но заметно упрощенное:
grep -P "STATUS: (?!Perfect)" recess.txt; test $? -eq 1
Что очень просто инвертирует код выхода, возвращая успех, только если текст не найден:
test 0 -eq 1
вернет 1.test 1 -eq 1
вернет 0.test 2 -eq 1
вернет 1.Это именно то, что я хотел: return 0, если совпадение не найдено, и 1 в противном случае.
Вам вообще не нужно использовать exit
. Логически, независимо от результата grep, ваш script все равно выйдет. Поскольку значение выхода оболочки script является кодом завершения последней команды, которая была запущена, просто запустите grep
как последнюю команду, используя опцию -v
, чтобы инвертировать совпадение для коррекции значения выхода. Таким образом, ваш script может свести к следующему:
grep -vqP "STATUS: (?!Perfect)" recess.txt
EDIT:
Извините, это не работает, если в файле есть другие типы строк. В интересах избежания выполнения нескольких команд, однако, awk
может выполнить весь shebang с чем-то вроде:
awk '/STATUS: / && ! /Perfect/{exit 1}' recess.txt
Если вы решите, что хотите получить данные, которые grep предоставил, вы можете сделать:
awk '/^STATUS: / && ! /Perfect/{print;ec=1} END{exit ec}' recess.txt
Чтобы он работал с set -e
, окружайте его в суб-оболочке с помощью (
и )
:
$ cat test.sh
#!/bin/bash
set -ex
(! ls /tmp/dne)
echo Success
$ ./test.sh
+ ls /tmp/dne
ls: cannot access /tmp/dne: No such file or directory
+ echo Success
Success
$ mkdir /tmp/dne
$ ./test.sh
+ ls /tmp/dne
$
Просто отрицание возвращаемого значения не работает в контексте set -e. Но вы можете сделать:
! grep -P "STATUS: (?!Perfect)" recess.txt || false
если кто-то получает здесь поиск bash манипуляции с кодом возврата:
(grep <search> <files> || exit 0 && exit 123;)
это вернет 0
(успех), когда grep ничего не обнаружит, и верните 123
(отказ), когда это произойдет. Скобки заключаются в том случае, если кто-либо проверит ее так же, как и в командной строке. с круглой скобкой он не выйдет из системы на выходе, а просто выйдет из подоболочки с тем же кодом ошибки.
Я использую его для быстрой проверки синтаксиса в файлах js:
find src/js/ -name \*js -exec node \{\} \; 2>&1 | grep -B 5 SyntaxError || exit 0 && exit 1;
Используйте специальную переменную ?
:
grep -P "STATUS: (?!Perfect)" recess.txt
exit $((1-$?))
(Но обратите внимание, что grep
также может возвращать 2, поэтому не ясно, что вы хотите встретить в таких случаях.)
Проблема с ответами grep заключается в том, что если файл пуст, вы также получаете чистый ответ, как если бы файл был совершенным. Поэтому лично я отказался от grep для этого и использовал awk.
awk 'BEGIN{ef=2}; /STATUS: Perfect/{ ef=0;}; /STATUS: Busted/{ print;eff=3;}; END{exit (ef+eff)}' a.txt ; echo $?
This has exit status:
0 : Perfect and !Busted
2 : !Perfect and Busted
3 : Perfect and Busted
5 : !Perfect and !Busted
[ $(grep -c -P "STATUS: (?!Perfect)" recess.txt) -eq 0 ]
Мне также понадобилось такое решение для написания марионетки только в том случае, если было сделано выражение, и придумал следующую команду:
/bin/grep --quiet 'root: [email protected]' /etc/aliases; if [ $? -eq 0 ]; then test 1 -eq 2; else test 1 -eq 1; fi;