Вы использовали синтаксис для подстановки процесса , которая передает выходные данные команды в качестве входных данных для другой команды. Но вам нужна была подстановка команды , которая захватывает вывод команды в виде строки. Подстановка команд использует $ (…)
.
SUFFIX=$( echo "&*645\[]}#@name" | sed -r 's/[^[:alnum:]]+/_/g' )
Обратите внимание, что если вы используете bash, вы можете сделать это с помощью его собственных встроенных конструкций. Если текст для очистки находится в переменной foo
:
shopt -s extglob
SUFFIX=${foo//+([^[:alnum:]])/_}
Да, 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>
<>
В оболочках 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
не будет содержать символы новой строки.