2016-07-19 5 views
0

В Solaris 10 я не могу правильно использовать grep. Мне просто нужно регулярное выражение, которое может соответствовать предложению, содержащему «яблоко» или «банан», и я пробовал в течение часа, но я не могу заставить его работать.(Solaris10 grep) Regex соответствует различным словам

#!/bin/sh 
# this is NOT bash 
# grep usage: grep -hblcnsviw pattern file . . . 

RESET='\033[0m' 
RED='\033[0;31m' 
GREEN='\033[0;32m' 
YELLOW='\033[0;33m' 

write() { 
    message=$1 

    if [ `echo $message | grep -c '^Success'` -gt 0 ] 
    then 
     echo "${GREEN}$message${RESET}" 
    elif [ `echo $message | grep -c '(apple|banana)'` -gt 0 ]   # doesn't work 
    then 
     echo "${YELLOW}$message${RESET}" 
    elif [ `echo $message | grep -c '^.*(apple|banana).*$'` -gt 0 ] # neither 
    then 
     echo "${YELLOW}$message${RESET}" 
    elif [ `echo $message | grep -c '/^.*(apple|banana).*$/'` -gt 0 ] # neither 
    then 
     echo "${YELLOW}$message${RESET}" 
    elif [ `echo $message | grep -c '^Error'` -gt 0 ] 
    then 
      echo "${RED}$message${RESET}" 
    fi 
} 

write 'Success' 
write 'Error' 
write 'banana' 

P.S. : Она работает очень хорошо, если мне нужно регулярное выражение для чего-нибудь еще, просто не яблоко или банан

+0

Предполагая, что ваша версия 'grep' поддерживает его, вы, вероятно, хотите« if echo »$ message» | grep -q '^ Success'; then' и т. д. вместо захвата вывода 'grep'. – chepner

ответ

1

По умолчанию grep использует формат Basic RegEx (BRE). Вы можете использовать egrep или grep -E, чтобы вместо grep использовать Extended RegEx (ERE).

ERE идентифицирует подвыражения в скобках так, как вы это делали в своем вопросе, то есть (..|..). Однако BRE использует \(..\|..\).

$ echo apple | grep -c '\(apple\|banana\)' 
1 
$ echo apple | grep -E -c '(apple|banana)' 
1 

Поиск "подвыражения" в Solaris grep man page.

Любой вариант будет работать для ваших тестов, вам просто нужно использовать правильный диалект для ваших вариантов grep .. или использовать правильные варианты grep для вашего диалекта.


В зависимости от вашего случая использования, вы можете рассмотреть вопрос об использовании case заявления вместо Grep.

case "$message" in 
    Success*)   colour="$GREEN" ;; 
    *apple*|*banana*) colour="$YELLOW" ;; 
    *plantain*)  colour="$YELLOW" ;; 
    Error*)   colour="$RED" ;; 
    *)     colour="$RED"; message="UNKNOWN" ;; 
esac 

printf '%s%s%s\n' "$colour" "$message" "$RESET" 

Обратите внимание, что модели в случае заявления обрабатываются с использованием Shell Patterns, а не регулярные выражения. Подробную информацию об простоте и ограничениях этой нотации см. В разделе «Генерация имени файла» man sh.

1

Try спасаясь трубы:

grep -c 'apple\|banana' 

И вам не нужны другие вещи.

+0

Я постараюсь, но не странно ли удалять трубку? Я думал, что трубу нужно интерпретировать. Означает ли это, что мне следует избегать других символов регулярных выражений, таких как пасетезис или фигурные скобки? –

+0

Нет. И да. Вроде. grep работает с BRE по умолчанию. Если вы избежите метасимвола BRE, он станет буквальным. В некоторых greps (например, GNU), если вы избегаете метасимволов ERE, они позволят их свойства ERE, даже когда grep работает в режиме BRE. Алгерически вызовите grep с аргументом '-E', а затем он будет использовать ERE вместо BRE, а затем вы не захотите избегать каких-либо метасимволов, если вы не хотите, чтобы все они были литералами. Так что узнайте о вариантах BRE и EREs и grep, а затем выберите, какие символы выходить очень осторожно. К счастью, ваша проблема не является кандидатом на использование grep. –

+0

Не работал для меня. Большое спасибо в любом случае –

0

Я считаю, что вам нужно использовать egrep (расширенный grep), чтобы использовать регулярные выражения с grep в оболочке bourne. Хотя я немного ржавый.

Чтобы проверить, запустить Bourne Shell:

/bin/sh 

введите:

$ echo banana | grep -c '(apple|banana)' 
0 
$ echo banana | egrep -c '(apple|banana)' 
1 

Интересно, а? Первый результат равен 0, поскольку он ищет всю строку '(apple|banana)', поэтому ваш скрипт терпит неудачу. интерпретирует задать расширенную строку как регулярное выражение, таким образом, она возвращает 1.

Больше испытаний:

$ echo apple | egrep -c '(apple|banana)' 
1 
$ echo Gabriel | egrep -c '(apple|banana)' 
0 
0

Оболочка - это среда, из которой можно вызвать инструменты, а не инструмент для манипулирования текстом. Инструмент для обработки текста UNIX общего назначения - awk. Поэтому вы должны писать сценарий AWK, а не сценарий оболочки, и это невероятно просто:

$ cat tst.awk 
function write(message, color) { 
    if  (message ~ /^Success/)  { color = green } 
    else if (message ~ /^(apple|banana)/) { color = yellow } 
    else if (message ~ /^Error/)   { color = red } 
    print color message reset 
} 

BEGIN { 
    reset = "\033[0m" 
    red = "\033[0;31m" 
    green = "\033[0;32m" 
    yellow = "\033[0;33m" 

    write("Success") 
    write("Error") 
    write("banana") 
} 

$ awk -f tst.awk 
Success 
Error 
banana 

Поверь мне выход правильно окрашенным.

btw по умолчанию awk на Solaris (/ bin/awk) является старым, сломанным awk и никогда не должен использоваться кем-либо по какой-либо причине. В Solaris используйте/usr/xpg4/bin/awk (или, что менее полезно, nawk).