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

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

Одним из распространенных применений является наличие переменной пути, и вы хотите извлечь имя каталога или расширение. Вы можете использовать для этого такие команды, как dirname или basename, но есть лучший способ, чем запуск процесса. Есть встроенные модификаторы. В Интернете вы найдете много примеров, которые удаляют что-то до или после определенного символа, но для этого есть лучшие модификаторы.

Поместим путь в переменную:

$ MYPATH="/path/to/image.png"
$ echo $MYPATH
/path/to/image.png

Есть 2 способа разбить путь. Первый — это голова/хвост, который разделяется по последней косой черте.

$ echo $MYPATH:h
/path/to
$ echo $MYPATH:t
image.png

Второй способ — root/extension, который разбивается на последней точке.

$ echo $MYPATH:r
/path/to/image
$ echo $MYPATH:e
png

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

$ echo $MYPATH:t:r
image

Это еще не все, но если вы используете их в строке, безопаснее использовать фигурные скобки вокруг переменной.

$ echo "This is my file name: ${MYPATH:t:r}"
This is my file name: image

Теперь еще один полезный, который дает вам абсолютный путь к переменной.

$ IMGPATH=img.png
$ echo ${IMGPATH:a}
/Users/me/img.png
# It works with nesting
$ IMGPATH=images/img.png
$ echo ${IMGPATH:a}
/Users/me/images/img.png
# It works with .. and . as well
$ IMGPATH="../victor/img.png"
$ echo ${IMGPATH:a}
/Users/victor/img.png

Обратите внимание, что пути, которые мы делаем абсолютными, не обязательно должны существовать. Модификатор просто выводит то, что было бы основано на текущем каталоге. И вместо этого вы можете использовать :A, если хотите разрешать символические ссылки.

Теперь модификатор :c выводит абсолютный путь имени команды, используя переменную PATH, как это сделала бы команда which.

$ MYCOMMAND=nvim
$ echo ${MYCOMMAND:c}
/usr/local/bin/nvim

Он также работает с обычными аргументами.

Если вы поместите его в backets, вы сможете использовать их в обычных аргументах, даже при подстановке. Эта команда, например, печатает все имена файлов C (без расширения), вложенные в каталог src.

$ print -l src/**/*.c(:t:r)

Другие модификаторы

Я знаю, что заголовок этой статьи относится к модификаторам «пути», но их не обязательно использовать в путях, если они делают то, что вы хотите. Кроме того, некоторые модификаторы не были созданы специально для путей, но их все равно можно использовать. Вот несколько.

Еще один полезный модификатор, который можно использовать для пути или чего-то еще, — это модификатор :s. Это типичный substitute, который вы найдете в grep и во многих других программах. Здесь мы копируем все текстовые файлы в другой с расширением markdown.

for file in *.txt; do
  cp ${file} ${file:s/txt/md/}
done

Как и многие другие инструменты замены, он работает только один раз. Если вы хотите заменить несколько раз, используйте вместо этого :gs.

$ MYFILE=css/main.css
$ echo ${MYFILE:gs/css/js/}
js/main.js

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

$ MYFILE=img/large/01.png
$ echo ${MYFILE:gs_/_._}
img.large.01.png

Вы можете заключать текст в кавычки с помощью :q и снимать кавычки с помощью :Q.

$ MYVAR="Hello zshell 'world'"
$ echo ${MYVAR:q}
Hello\ zshell\ \'world\'
$ MYVAR="Hello\ zshell\ \'world\'"
$ echo ${MYVAR:q}
Hello zshell 'world'

Очевидно, вы можете сделать переменную либо строчной, либо прописной.

$ MYVAR="MAKE ME WHISPER"
$ echo ${MYVAR:l}
make me whisper
$ MYVAR="make me shout"
$ echo ${MYVAR:u}
MAKE ME SHOUT

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

$ MYVAR="hello world"
$ echo ${(C)MYVAR}
Hello World

Наконец, очень полезная функция — извлечение подстроки. Для этого вы используете 2 числа, представляющие индекс первого символа и последнего (исключено). Почему-то отрицательный индекс (с конца) работает на второе число, а не на первое. Не стесняйтесь связаться с нами, вы знаете почему.

$ MYDIGITS="0123456789"
$ echo ${MYDIGITS:0:4}
012
$ echo ${MYDIGITS:0:-2}
01234567
# You can omit the second number if you want the end of the string
$ echo ${MYDIGITS:2}
23456789

Вывод

Этот список модификаторов не является полным, и есть много других вещей, которые нужно узнать о zshell. Я призываю вас прочитать больше об этом. Эта страница любителей zsh — хорошее начало.