Регулярные выражения 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 шт):
Используйте [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. См. документацию на англ. языке.
раз в заголовке и среди меток присутствует название программы 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