Регулярные выражения Bash

Возникла задача парсинга IP из строки в Bash скрипте. Пытаюсь сделать так:

echo "1.1.1.1 asdsad" | awk '/((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)/{print $0}'

В ответ:

awk: cmd. line:1: warning: regexp escape sequence `\d' is not a known regexp operator

Подскажите, что здесь не так? Как можно реализовать мою задачу иначе?


Ответы (2 шт):

Автор решения: Wiktor Stribiżew

Используйте [0-9] вместо \d, так как POSIX ERE не поддерживает второй шаблон.

regex='((25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})'
echo "1.1.1.1 asdsad" | \
 awk -v rx="$regex" 'match($0,rx){print substr($0,RSTART,RLENGTH)}'

См. пример работы скрипта онлайн.

Тут все \d заменены [0-9], а \d\d? заменены [0-9]{1,2}.

С помощью -v rx="$regex" переменную с шаблоном IP-адреса можно передать в код программы awk, так легче работать с длинными шаблонами.

Кстати, ваш скрипт возвращает все целые строки, в которых было найдено совпадение. Чтобы найти и вернуть само совпадение с помощью awk, надо воспользоваться функцией match, которая ищет первое слева самое длинное совпадение и возваращает начальную позицию (индекс) найденной подстроки (1 если совпадение найдено в начале строки). Если совпадение не найдено, возвращается нуль. Эта функция также устанавливает значения предварительно определенных переменных RSTART (начальная позиция совпадения) и RLENGTH (длина найденной подстроки). Если совпадение не найдено, RSTART равен нулю, а RLENGTH-1. См. документацию на англ. языке.

→ Ссылка
Автор решения: aleksandr barakin

раз в заголовке и среди меток присутствует название программы bash, я думаю, что решение средствами этой программы будет всё-таки «в тему»:

$ cat script
while read l; do
  for w in $l; do
    echo $w | while IFS='.' read n1 n2 n3 n4 o; do
      if [ -z "$o" -a \
        "$n1" -le 255 -a "$n1" -ge 0 -a \
        "$n2" -le 255 -a "$n2" -ge 0 -a  \
        "$n3" -le 255 -a "$n3" -ge 0 -a  \
        "$n4" -le 255 -a "$n4" -ge 0 ] 2>/dev/null; then
        echo "$n1.$n2.$n3.$n4"
      fi
    done
  done
done
$ cat testfile
1.2.3.4 1.2.3.4.5 bac
1.2.3,4 1.2.113.4 a.b.c.d
255.255.255.255 1.2.3.-4 4.5.6
255.255.255.256
$ cat testfile | bash script
1.2.3.4
1.2.113.4
255.255.255.255

впрочем, ничто не препятствует и тому, чтобы использовать как интерпретатор любую posix-совместимую оболочку. результат будет аналогичный:

$ cat testfile | sh script
1.2.3.4
1.2.113.4
255.255.255.255
→ Ссылка