Может ли PATH содержать новые строки?

Вы использовали синтаксис для подстановки процесса , которая передает выходные данные команды в качестве входных данных для другой команды. Но вам нужна была подстановка команды , которая захватывает вывод команды в виде строки. Подстановка команд использует $ (…) .

SUFFIX=$( echo "&*645\[]}#@name" | sed -r 's/[^[:alnum:]]+/_/g' )

Обратите внимание, что если вы используете bash, вы можете сделать это с помощью его собственных встроенных конструкций. Если текст для очистки находится в переменной foo :

shopt -s extglob
SUFFIX=${foo//+([^[:alnum:]])/_}

3
31.12.2018, 12:39
2 ответа

Да, PATHможет содержать символы новой строки (даже в древней системе Unix ).

Что касается разделения любой строки в оболочке, единственный переносимый способ сделать это — IFS. Однако вы можете использовать IFS=:; set -f; set -- $PATHили передать его функции вместо цикла с for.

С помощью bashвы также можете "читать" строку в массив :

xtra=$'some\nother\nplace\n\n'; PATH="$PATH:$xtra"
mapfile -td: path < <(printf %s "$PATH")
printf '<%s>\n' "${path[@]}"

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

Обратите внимание, что IFSбудет завершать поля, а не разделять их (примерно так же, как \nв конце файла не будет рассматриваться как пустая строка программами, читающими файл строка -на -строка ); если это не то, что ожидается, и вы действительно хотите создать дополнительное пустое поле в конце при разбиении строки, которая заканчивается символом из IFS, вы должны присоединиться к пустой строке после переменной, которая подлежит разбиению на слова:

(P=/bin:; IFS=:; printf '<%s>\n' $P"")
</bin>
<>

Алгоритм разделения слов также будет игнорировать пробельные символы в начале строки, если эти пробельные символы являются частью IFS.Если вам нужно дополнительное поле для начального пробела, вы также должны добавить пустую строку перед переменной:

(P='   foo : bar  '; IFS=': '; set -f; set -- $P; printf '<%s>\n' "$@")
<foo>
<bar>

(P='   foo : bar  '; IFS=': '; set -f; set -- ""$P""; printf '<%s>\n' "$@")
<>
<foo>
<bar>
<>
1
27.01.2020, 21:17

В оболочках POSIX $IFSявляется полем разделителем , а не разделителем, поэтому значение $PATH, например /bin:/usr/bin:, будет разделено на /binи /usr/binвместо /bin., /usr/binи пустая строка (, означающая текущий каталог ). Вам нужно:

IFS=:; set -o noglob
for var in $PATH""; do
  printf '<%s>\n' "$var"
done

Чтобы избежать изменения глобальных настроек, вы можете использовать оболочку с явными операторами разделения, напримерzsh:

for var in "${(s/:/@)PATH}"; do
  printf '<%s>\n' "$var"
done

Хотя в этом случае zshуже имеет массив $path, привязанный к $PATH, как в csh/ tcsh, поэтому:

for var in "$path[@]"; do
  printf '<%s>\n' "$var"
done

В любом случае, да, теоретически $PATHкак и любая переменная может содержать символы новой строки, символ новой строки никоим образом не является особенным, когда речь идет о разрешении пути к файлу. Я не ожидаю, что кто-нибудь здравомыслящий поместит каталог с новой строкой (или подстановочными знаками )в свой $PATHили назовет команду с новой строкой в ​​ее имени. Также трудно представить себе сценарий, в котором кто-то может использовать скрипт, который предполагает, что $PATHне будет содержать символы новой строки.

4
27.01.2020, 21:17

Теги

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