Вопрос или проблема
Как я могу заключить строку в одинарные кавычки?
Например, я могу сделать:
$ printf "%q\n" 'два слова'
два\ слова
$
Есть ли способ получить строку в одинарных (или двойных) кавычках в выводе, т.е.
$ MAGIC 'два слова'
'два слова'
$
Мне гораздо легче читать версию в одинарных кавычках.
Я хотел бы ответ, который работает для {ba,z}sh. POSIX shell был бы бонусом.
Предположим, что:
$ value=$'Это не \n\x1b "правильный" тест'
$ printf '%s\n' "$value"
Это не
"правильный" тест
posixquote () { printf %s\\n "$1" | sed "s/"https://unix.stackexchange.com/"\\\\''/g;1s/^/'/;\$s/\$/"https://unix.stackexchange.com/" ; }
Используйте:
$ quote "${value}"
'Это не
"правильный" тест'
Эта функция просто заменяет каждую встречающуюся «
'
» (одинарная кавычка) в строке на «'\''
» (одинарная кавычка, обратный слэш, одинарная кавычка, одинарная кавычка), затем ставит одинарные кавычки в начале и конце строки. Поскольку единственный символ, который имеет специальное значение в одинарных кавычках, это сама одинарная кавычка, это абсолютно безопасно. Концевые символы новой строки обрабатываются правильно, а одинарная кавычка в конце служит как безопасный символ, чтобы предотвратить подстановку команды от уничтожения концевых символов новой строки, если кто-то хочет сделать что-то вроде:quoted=$(quote "$var")
Предупреждение: символы ESC (\033 или \x1b или десятичное 27) выше (технически)Quoted, но невидимы. При отправке в терминал, как и другие управляющие символы, они могут даже причинить вред. Только тогда, когда они визуально представлены как $’\033′, $’\C-[‘ или $’\E’, они явно видимы и однозначны.
bashprintf '%s\n' "${value@Q}" $'Это не \n\E "правильный" тест'
zshprintf '%s\n' ${(q)value} Это\ не\'\ $'\n'$'\033'\ "правильный"\ тест
zshprintf '%s\n' ${(qq)value} 'Это не\'\
"правильный" тест'
zshprintf '%s\n' ${(qqq)value} "Это не
\"правильный\" тест"
zshprintf '%s\n' ${(qqqq)value} $'Это не \n\033 "правильный" тест'
zshprintf '%s\n' ${(q-)value} 'Это не\'\
"правильный" тест'
zshprintf '%s\n' ${(q+)value} $'Это не \n\C-[ "правильный" тест'
Будьте осторожны с некоторыми строками, заключенными в кавычки в zsh: символы ESC (\033 или \x1b или десятичное 27), указанные выше, все (технически) заключены в кавычки, но невидимы. При отправке в терминал, как и другие управляющие символы, они могут даже причинить вред. Только тогда, когда они визуально представлены как $’\033′, $’\C-[‘ или $’\E’, они явно видимы и однозначны.
${parameter@operator}
Q
Расширение — это строка, которая является значением параметра, заключенной в кавычки в формате, который можно повторно использовать в качестве ввода.
Из zshexpn
man page:
q
Заключите символы, которые являются специальными для оболочки, в результирующих словах в обратные слэши; непечатаемые или недопустимые символы заключаются в кавычки с использованием формы$'\NNN'
, с отдельными кавычками для каждого октета.Если этот флаг задан дважды, результирующие слова заключаются в одинарные кавычки, а если он задан трижды, слова заключаются в двойные кавычки; в этих формах не осуществляется специальная обработка непечатаемых или недопустимых символов. Если флаг задан четыре раза, слова заключаются в одинарные кавычки, предшествующие
$
. Обратите внимание, что во всех трёх этих формах кавычки ставятся безусловно, даже если это не изменяет способ, которым результирующая строка будет интерпретироваться оболочкой.Если указано
q-
(может появиться только единственныйq
), используется минимальная форма одинарного заключения, которая заключает строку в кавычки только при необходимости защитить специальные символы. Обычно эта форма дает наиболее читаемый вывод.Если указан
q+
, используется расширенная форма минимального заключения, которая заставляет непечатаемые символы отображаться с использованием$'...'
. Это заключение аналогично тому, что используется в выводе значений командами семьи typeset.
Zsh имеет множество вариантов заключения, которые могут быть применены к расширению параметров:
q
Заключите символы, которые являются специальными для оболочки, в результирующих словах в обратные слэши; непечатаемые или недопустимые символы заключаются в кавычки, используя форму
$'\NNN'
, с отдельными кавычками для каждого октета.Если этот флаг указан дважды, результатирующие слова заключаются в одинарные кавычки, а если он указан трижды, слова заключаются в двойные кавычки; в этих формах ни одна специальная обработка непечатаемых или недопустимых символов не осуществляется. Если флаг указан четыре раза, слова заключаются в одинарные кавычки, предшествующие
$
. Обратите внимание, что во всех трех этих формах кавычки ставятся без условий, даже если это не меняет способ, которым результирующая строка будет интерпретироваться оболочкой.Если указан
q-
(может появиться только единственныйq
), используется минимальная форма одинарного заключения, которая заключает строку в кавычки только при необходимости, чтобы защитить специальные символы. Обычно эта форма дает наиболее читаемый вывод.Если указан
q+
, используется расширенная форма минимального заключения, которая заставляет непечатаемые символы отображаться с использованием$'...'
. Это заключение аналогично тому, что используется в выводе значений командами семьи typeset.
Таким образом, функция, подобная:
MAGIC () {
printf "%s\n" "${(q+)@}"
}
Даст вывод, подобный:
$ MAGIC 'два слова'
'два слова'
$ MAGIC 'два слова "'
'два слова "'
$ MAGIC 'два '"'"'слова'
'два '\''слова'
Как насчет этого элементарного решения zsh
?
#!/bin/zsh
# Проходим по позиционным параметрам, включая пустые
for arg in "${(@)argv}";
do
# Выводим без новой строки: заключенное значение параметра плюс пробел
echo -n "'$arg' "
done
# Финальная новая строка
echo
Это делает следующее:
$ MAGIC 'два слова'
'два слова'
$ MAGIC a b c "x" "y" "z" '' "" ok
'a' 'b' 'c' 'x' 'y' 'z' '' '' 'ok'
Ответ или решение
Краткий обзор
Вопрос заключается в том, как экранировать строки с использованием одинарных кавычек вместо обратных слешей в оболочке UNIX (bash, zsh и POSIX). Такой подход может значительно улучшить читаемость кода, особенно когда речь идет о строках, содержащих пробелы или специальные символы. В данной статье мы рассмотрим несколько методов выполнения этой задачи.
Использование printf
для экранирования строк
Одним из способов выполнить экранирование строк является использование команды printf
. Эта команда позволяет подготовить строку в формате, который можно использовать в терминале. Стандартный подход выглядит следующим образом:
printf "%q\n" 'two words'
Этот код экранирует пробел в строке, выведя:
two\ words
Однако чётко заданный цель — предствить строку, заключённую в одинарные кавычки.
Функции для экранирования строк
Для достижения желаемого результата можно создать небольшую функцию на оболочке bash
или zsh
.
Пример функции quote
Вот пример, как реализовать такую функцию в bash
:
quote () {
// Заменяем все одинарные кавычки на \' и добавляем кавычки вначале и в конце
printf '%s\n' "$1" | sed "s/'/'\\''/g;1s/^/'/;\$s/\$/'/"
}
Использование этой функции:
value="This isn't a test"
quoted=$(quote "$value")
echo "$quoted"
Вывод будет таким:
'This isn'\''t a test'
В этом решении ответ корректно экранирует одинарные кавычки в строке.
Решения для zsh
Если вы используете zsh
, вы можете воспользоваться следующими методами, чтобы легко экранировать строки.
MAGIC () {
printf "%s\n" "${(q+)@}"
}
Таким образом, вызов функции MAGIC
с аргументом:
MAGIC 'two words'
выведет:
'two words'
Вы также можете вызвать функцию с несколькими аргументами:
MAGIC 'two words' 'another one'
И результат будет:
'two words' 'another one'
POSIX-совместимое решение
Для тех, кто ищет совместимое с POSIX решение, ниже приведен пример, который будет работать в любой оболочке, поддерживающей базовые конструкции:
tail=$1
quoted=""
sq="'"
while [ -n "$tail" ]; do
case "$tail" in
'') false;;
\'*) quoted="$quoted\\'"; tail="${tail#?}";;
[!\']*\'*) quoted="$quoted'${tail%%$sq*}'\\'"; tail="${tail#*$sq}";;
*) quoted="$quoted'${tail%%$sq*}'"; false;;
esac
done
[ -z "$quoted" ] && quoted="''"
echo "$quoted"
Заключение
В этой статье мы обсудили, как можно легко экранировать строки с использованием одинарных кавычек в оболочках bash
, zsh
и POSIX. Мы рассмотрели примеры, которые показывают, как добиться желаемого результата с использованием printf
, функций и конструкций оболочки. Эти методы позволяют улучшить читаемость скриптов и избегать путаницы в строках с пробелами или специальными символами.
SEO оптимизация
Чтобы улучшить видимость данной статьи в поисковых системах, вы можете использовать ключевые слова, такие как "экранирование строк в оболочке", "одинарные кавычки bash", "zsh экранирование строк" и т. д., чтобы привлечь внимание к теме экранирования строк с одинарными кавычками.