bash-WTF: `foo` != $(foo)

Oct 06, 2011 11:14

А я тут замечательный WTF в sh встретил.

Есть строчка /var/log/daemon/api/*.log и нужно получить из неё регулярку для sed - т.е. поэскейпить звёздочку и точку.
Очевидное решение:
$ log="/var/log/daemon/api/*.log"
$ echo "$log" | sed 's/[\.\*]/\\&/g'
/var/log/daemon/api/\*\.log

Но есть пара неочевидных тонкостей:
$ log="/var/log/daemon/api/*.log"
$ echo "$log" | sed 's/[\.\*]/\\&/g'
/var/log/daemon/api/\*\.log
$ relog=`echo "$log" | sed 's/[\.\*]/\\&/g'`; echo $relog
/var/log/daemon/api/&&log
$ relog=$(echo "$log" | sed 's/[\.\*]/\\&/g'); echo $relog
/var/log/daemon/api/\*\.log
$ relog=`echo "$log" | sed 's/[\.\*]/\\\\&/g'`; echo $relog
/var/log/daemon/api/\*\.log

Отсюда важный вывод, о котором стоит помнить - escaping внутри `foo` и $(foo) работает по-разному.
Проверено на sh из FreeBSD-8.2, bash-4.1.10, bash-4.2.8, dash-0.5.5.1-7.2ubuntu1.

UPD: Впрочем, в man bash этот факт описан. :)

linux, sh, dash, **it, freebsd, bash

Previous post Next post
Up