Неправильное поведение в grep с @s - PullRequest
0 голосов
/ 25 мая 2018

Я писал небольшую оболочку для nullmailer, когда заметил, imho, нежелательное поведение в grep.В частности, я заметил кое-что странное с @ s.

. Он разрывает строки, содержащие @, и дает неправильный вывод.

TL; DR

E-адреса электронной почты имеют некоторые правила (EG RFC 2822 ), поэтому я буду использовать заведомо неправильное регулярное выражение для них, просто чтобы сделать его немного короче.Обратите внимание, что это не изменит проблему, о которой я спрашиваю.

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

Я написал небольшой скрипт, чтобы помочь мне объяснить, что я «нашел»:

#!/bin/bash

funct1() {

  arr=(local1@domain.tld local2@domain.tld)
  regex="[[:alnum:]]*@[[:alpha:]]*\.[[:alpha:]]\{2,\}"
  for dest in ${arr[@]}; do
    printf "%s\n" "$dest" | grep -o -e "$regex"
  done
}
funct2() {
  arr=(local1@domain.tld local2@domain.tld)
  regex="[[:alpha:]]*@[[:alpha:]]*\.[[:alpha:]]\{2,\}"
  for dest in ${arr[@]}; do
    printf "%s\n" "$dest" | grep -o -e "$regex"
  done
}

funct3(){
  arr=(local1@dom1@ain.tld local2@dom2@ain.tld)
  regex="[[:alpha:]]*@[[:alpha:]]*@[[:alpha:]]*\.[[:alpha:]]\{2,\}"
  for dest in ${arr[@]}; do
    printf "%s\n" "$dest" | grep -o -e "$regex"
  done
}

funct4(){
  arr=(local1@dom1@ain.tld local2@dom2@ain.tld)
  regex="[[:alpha:]]*@[[:alnum:]]*@[[:alpha:]]*\.[[:alpha:]]\{2,\}"
  for dest in ${arr[@]}; do
    printf "%s\n" "$dest" | grep -o -e "$regex"
  done
}

printf "One @, all parts of regex right:\n"
funct1
printf "One @, first part of regex wrong:\n"
funct2
printf "Two @, first and second part of regex wrong:\n"
funct3
printf "Two @, first part of regex wrong:\n"
funct4
exit 0

Чтобы лучше понять проблему, я использовал два типа строк: local1@domain.tld и local1@dom1@ain.tld, и кажется,мне, что grep не ведет себя должным образом со строками, содержащими по крайней мере @.

Вывод:

One @, all parts of regex right:
local1@domain.tld
local2@domain.tld

One @, first part of regex wrong:
@domain.tld
@domain.tld

Two @, first and second part of regex wrong:

Two @, first part of regex wrong:
@dom1@ain.tld
@dom2@ain.tld

funct1 имеет регулярное выражение, которое решает все строкитак что нет проблем, все они печатаются.

funct2 имеет регулярное выражение, которое решает только строки от @ до конца, так что я должен ожидать, что нет вывода, из-за неправильного выражения;вместо этого у меня есть вторая часть строк ...

Именно поэтому я решил добавить второй @ в строку и выполнить несколько тестов.

funct3 решает толькостроки от второго @ до конца, так что я должен ожидать вообще никакого вывода из-за ошибки в регулярном выражении;Хорошо, ничего не выводится.

funct4 вместо этого имеет регулярное выражение, которое решает только строки от первого @ до конца, поэтому я должен ожидать, что он не может ничего мне показать;вместо этого, то, что у меня есть, это выход первого @, как funct2.

За исключением funct1 У меня вообще не должно быть никакого вывода, я прав?

Почемуgrep прерывает результат при первом @?

Я считаю это нежелательным поведением, потому что таким образом результат будет состоять из строк, которые не полностью соответствуют моему выражению.

Я что-то упустил?

РЕДАКТИРОВАТЬ: тег удаления undefined-behavior

1 Ответ

0 голосов
/ 26 мая 2018

У вашего регулярного выражения есть проблемы, работающие как задуманоВы также можете просто посчитать число @ в качестве теста.Лично я бы создал логический метод, подобный этому:

#!/bin/bash

# -- is email address valid ? --    
function isEmailValid() {
      echo "$1" | egrep -q "^([A-Za-z]+[A-Za-z0-9]*((\.|\-|\_)?[A-Za-z]+[A-Za-z0-9]*){1,})@(([A-Za-z]+[A-Za-z0-9]*)+((\.|\-|\_)?([A-Za-z]+[A-Za-z0-9]*)+){1,})+\.([A-Za-z]{2,})+"
}


if isEmailValid "_#@us@.com" ;then
        echo "VALID "
else
        echo "INVALID"
fi


if isEmailValid "us@ibm.com" ;then
        echo "VALID "
else
        echo "INVALID"
fi

Или проще:

function isEmailValid() {
      regex="^([A-Za-z]+[A-Za-z0-9]*((\.|\-|\_)?[A-Za-z]+[A-Za-z0-9]*){1,})@(([A-Za-z]+[A-Za-z0-9]*)+((\.|\-|\_)?([A-Za-z]+[A-Za-z0-9]*)+){1,})+\.([A-Za-z]{2,})+"
      [[ "${1}" =~ $regex ]]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...