2013-03-12 1 views
23

Как уменьшить следующий скрипт bash?Bash: однострочный выход для выхода с противоположным статусом команды grep?

grep -P "STATUS: (?!Perfect)" recess.txt && exit 1 
exit 0 

Похоже, что я смогу сделать это с помощью одной команды, но у меня здесь всего 3.

Моя программа должна:

  • Read recess.txt
  • Выход 1 (или не ноль), если она содержит строку с "STATUS:" НЕ из "Perfect"
  • Выход 0, если нет такой линии (т. е. все строки «СТАТУС:» являются «совершенными»)

Награда за ответ относится к самому строгому сценарию. Благодаря!

Пример файлов

Программа должна иметь статус выхода 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's should not be styled 
     1. #asdf 
+0

Это должно идти на PPCG. – clap

ответ

22

Только negate возвращаемое значение.

! grep -P "STATUS: (?!Perfect)" recess.txt 
+0

Это то, что я искал. Спасибо –

+2

Не работает с set -e. Пожалуйста, см. Мой ответ. –

+3

Работает с set -e, если вы используете(). См. Мой ответ. – Robpol86

1

Использование special ? variable:

grep -P "STATUS: (?!Perfect)" recess.txt 
exit $((1-$?)) 

(Но обратите внимание, что grep может также возвращать 2, так что не ясно, что вы хотели бы произойти в таких случаях.)

+0

Я согласен с вашим комментарием выше - однострочный вкладыш не является особенно полезным. Я на самом деле просто ищу способ сглаживать эту вещь, которая кажется, что это должно быть легко. Я сказал в вопросе, что я бы наградил его самым строгим кодом. У вас классный трюк, о котором я не знал, но он кажется хрупким, если grep может вернуть статус 2 (чего я не знал). Спасибо хоть! –

+0

@SeanAdkinson: Все в порядке, я не боролся за upvotes, просто любопытно, что цель была здесь;) –

+0

Чтобы исправить проблему с 'grep', возвращающим код выхода 2 при ошибке, вы можете сделать' exit $ (($?^1)) ', который только переворачивает младший бит. Это сохраняет бит ошибки для 2, который, я думаю, является тем, что вы обычно хотели бы. –

6

Вы на самом деле не нужно использовать exit вообще. По логике, независимо от результата grep, ваш скрипт все равно выйдет. Поскольку значением выхода скрипта оболочки является код выхода последней команды, которая была запущена, просто запустите grep в качестве последней команды, используя опцию -v, чтобы инвертировать совпадение для коррекции значения выхода. Таким образом, ваш сценарий может уменьшить просто:

grep -vqP "STATUS: (?!Perfect)" recess.txt 

EDIT:

К сожалению, выше не работает, когда есть другие типы строк в файле. В интересах предотвращения запуска нескольких команд, хотя, awk может выполнить весь притон с чем-то вроде:

awk '/STATUS:/&& ! /Perfect/{exit 1}' recess.txt 

Если вы решили, что хотите вывод, который обеспечил бы Grep, вы можете сделать:

awk '/^STATUS:/&& ! /Perfect/{print;ec=1} END{exit ec}' recess.txt 
+1

Да, это была одна из первых вещей, которые я пробовал, но этот вопрос тонко сложнее. Вы видите, что с помощью «-v» он просто возвращает каждую строку файла, которая всегда будет давать мне статус выхода «0» в grep, если что-то будет возвращено. К сожалению, это не совсем соответствует требованиям моей программы. –

+0

Вот почему я добавил '-q' - ваш список требований никогда не указывал, что вы заботились о выходе' grep' :) –

+0

Правильно, я не забочусь о выходе, но для моего разбитого файла (добавлен вопрос) код выхода по-прежнему «0», используя эту команду –

0

мне нужно такое решение для написания марионетки, только если заявления и пришли с помощью следующей команды:

/bin/grep --quiet 'root: [email protected]' /etc/aliases; if [ $? -eq 0 ]; then test 1 -eq 2; else test 1 -eq 1; fi;

9

Я наткнулся на это, нуждаясь в onlyif заявлении для кукол , Таким образом, Tgr's bash solution не будет работать, и я не хотел бы расширять сложность, как в Christopher Neylan's answer.

Я закончил с использованием версии вдохновленный Henri Schomäcker's answer, но заметно упрощается:

grep -P "STATUS: (?!Perfect)" recess.txt; test $? -eq 1 

Что очень просто инвертирует код завершения, возвращая успех только если текст не найден:

  • Если grep возвращает 0 (найдено совпадение), test 0 -eq 1 вернется 1.
  • Если grep возвращает 1 (не найдено найдено), test 1 -eq 1 вернет 0.
  • Если Grep возвращает 2 (ошибка), test 2 -eq 1 возвратит 1.

Какой именно то, что я хотел: вернуться 0, если совпадение не найдено, и 1 в противном случае.

+0

Хорошо подходит для 'grep -v' (инвертировать). – hakre

4

Просто отрицание возвращаемого значения не работает в контексте set -e. Но вы можете сделать:

! grep -P "STATUS: (?!Perfect)" recess.txt || false 
6

Чтобы заставить его работать с 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 
$ 
1

Проблема с 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 
+0

Ничего, я не думал о случае с пустым файлом. +1 –

5

если кто получает здесь ищет Баш манипуляции код возврата:

(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;