Различия в белых пробегах между сценарием Bash и интерактивной оболочкой

Вот oneliner, который показывает команду для выполнения :

echo kill $(sudo netstat -anp | awk '/ LISTEN / {if($4 ~ ":80$") { gsub("/.*","",$7); print $7; exit } }')

Замените echo на sudo, чтобы процесс действительно был убит.

2
08.01.2018, 22:07
1 ответ

Я могу воспроизвести такое поведение только в двух случаях:

  1. двойная -подстановка команды в кавычках:

    #!/bin/bash
    
    str="a b c d"
    printf "%s\n"  "`echo $str`"
    
  2. или измененная переменная внутреннего разделителя полей(IFS), например.:

    #!/bin/bash
    
    IFS=,
    str="a b c d"
    printf "%s\n" `echo $str`
    

В обоих случаях вывод

$./test.sh
a b c d

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

IFS=$' \t\n'

Небольшое пояснение, почему вывод отличается при изменении IFSи что общего у него с двойными -кавычками?

Начнем с конца:

printf "%s\n" a b c d

явно отличается от

printf "%s\n" 'a b c d'

В первом случае у нас есть четыре отдельных слова, и printfвыводим их одно за другим, добавляя к ним новую строку. Во втором случае все a b c dобрабатывается как одно слово, и printfпросто выводит его как таковое на терминал. И теперь должно быть очевидно, что вывод `echo $str`обрабатывается как одно слово, если дополнительно -цитируется дважды.

Теперь IFSначинает играть свою роль. А именно, tt используется для разделения слов после расширений, поэтому по умолчанию IFS=$' \t\n'выражение echo a b c dвыводит a b c d, но с IFS=,оно становится'a b c d'-единым миром, хотя кавычки явно не использовались.Нагляднее это можно проверить без переменной:

$ IFS=,
$ printf "%s\n"  `echo a b c d`
a b c d

$ IFS=$' \t\n'
$ printf "%s\n"  `echo a b c d`
a
b
c
d

В качестве последнего замечания :лучше использовать $()форму подстановки команд, а не обратные кавычки, но это другая тема.

4
27.01.2020, 21:58

Теги

Похожие вопросы