2014-02-20 2 views
0

Может кто-нибудь объяснить это поведение Баш оболочки, которая сводит меня с умастранный выход эхо

[[email protected] bin]# export test=`whois -h whois.lacnic.net 187.14.6.108 | grep -i inetnum: | awk '{print $2}'` 

[[email protected] bin]# echo $test 
187.12/14 

[[email protected] bin]# echo "iptables -I INPUT -s $test -J DROP" 

-J DROP -I INPUT -s 187.12/14 

[[email protected] bin]# 

Почему мой echo облажался? Он изменяется по содержимому $test.

Если вы изменили $test на "ABC", все в порядке. Связано ли это с косой чертой?

+1

Я подозреваю, что в '$ test' могут быть некоторые невидимые символы, такие как возврат каретки, что заставляет' -J DROP' делать резервную копию и перезаписывать 'iptables' на выходе. Другими словами, строка «187.12/14», вероятно, что-то вроде «\ r187.12.14» или что-то в этом роде. – lurker

+0

@devnull - не имеет отношения к | - Я думаю, что mbratch верна. –

+0

@JimHolland. Форматирование вызвало обратные шаги (подмена команды) как _invisible_. Мне показалось, что вы используете команду с '|' как переменную. – devnull

ответ

1

Почему мой echo напортачил? Он изменяется в соответствии с содержанием $test.

Поскольку ваш номер test содержит возврат каретки. Удалить его:

test=$(whois -h whois.lacnic.net 187.14.6.108 | grep -i inetnum: | awk '{print $2}' | tr -d '\r') 
1

Ваш test содержит что-то вроде

1234567 -I INPUT -s 187.12/14\r-J DROP 

, который, из-за возврата каретки, которая видна только

-J DROP -I INPUT -s 187.12/14 

ЧР перемещает курсор в Пуск- в которой он затем перезаписывает предыдущие символы.

Вы можете попробовать

echo "$test" | od -bc 

, чтобы проверить это.

1

Это почти наверняка возврат каретки. echo выполняет свою работу правильно и испускает строку на ваш терминал; проблема заключается в том, что ваш терминал обрабатывает часть строки в качестве команды для ее последующего (в частности, LF-символ, $'\r', сообщая ему отправить курсор в начало существующей строки).

Если вы хотите видеть содержимое $test способом, который не позволяет вашему терминалу интерпретировать escape-последовательности или другие управляющие символы, запустите следующее (обратите внимание, что строка формата %q является расширением bash, недоступным в чисто POSIX система):

printf '%q\n' "$test" 

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

Чтобы удалить $'\r', который почти наверняка персонаж дает вам неприятности, вы можете запустить следующее разложение параметра:

test=${test//$'\r'/} 

В отличие от решений, требующих трубопроводов запуск дополнительного процесса (например, tr), это происходит внутри уже запущенная оболочка bash и, следовательно, более эффективна.