оболочка: Оформите строку цитаты одинарными кавычками, а не обратными косыми чертами

Вопрос или проблема

Как я могу заключить строку в одинарные кавычки?

Например, я могу сделать:

$ printf "%q\n" 'два слова'
два\ слова
$

Есть ли способ получить строку в одинарных (или двойных) кавычках в выводе, т.е.

$ MAGIC 'два слова'
'два слова'
$

Мне гораздо легче читать версию в одинарных кавычках.

Я хотел бы ответ, который работает для {ba,z}sh. POSIX shell был бы бонусом.

Предположим, что:

$ value=$'Это не \n\x1b "правильный" тест'
$ printf '%s\n' "$value"
Это не
"правильный" тест

quote () { printf %s\\n "$1" | sed "s/"https://unix.stackexchange.com/"\\\\''/g;1s/^/'/;\$s/\$/"https://unix.stackexchange.com/" ; }

Используйте:

$ quote "${value}"
'Это не
"правильный" тест'

Из sh трюки Рича

Эта функция просто заменяет каждую встречающуюся «'» (одинарная кавычка) в строке на «'\''» (одинарная кавычка, обратный слэш, одинарная кавычка, одинарная кавычка), затем ставит одинарные кавычки в начале и конце строки. Поскольку единственный символ, который имеет специальное значение в одинарных кавычках, это сама одинарная кавычка, это абсолютно безопасно. Концевые символы новой строки обрабатываются правильно, а одинарная кавычка в конце служит как безопасный символ, чтобы предотвратить подстановку команды от уничтожения концевых символов новой строки, если кто-то хочет сделать что-то вроде:

 quoted=$(quote "$var")

Предупреждение: символы ESC (\033 или \x1b или десятичное 27) выше (технически)Quoted, но невидимы. При отправке в терминал, как и другие управляющие символы, они могут даже причинить вред. Только тогда, когда они визуально представлены как $’\033′, $’\C-[‘ или $’\E’, они явно видимы и однозначны.

printf '%s\n' "${value@Q}" $'Это не \n\E "правильный" тест'

printf '%s\n' ${(q)value} Это\ не\'\ $'\n'$'\033'\ "правильный"\ тест
printf '%s\n' ${(qq)value} 'Это не\'\
"правильный" тест'

printf '%s\n' ${(qqq)value} "Это не
\"правильный\" тест"

printf '%s\n' ${(qqqq)value} $'Это не \n\033 "правильный" тест'
printf '%s\n' ${(q-)value} 'Это не\'\
"правильный" тест'

printf '%s\n' ${(q+)value} $'Это не \n\C-[ "правильный" тест'

Будьте осторожны с некоторыми строками, заключенными в кавычки в zsh: символы ESC (\033 или \x1b или десятичное 27), указанные выше, все (технически) заключены в кавычки, но невидимы. При отправке в терминал, как и другие управляющие символы, они могут даже причинить вред. Только тогда, когда они визуально представлены как $’\033′, $’\C-[‘ или $’\E’, они явно видимы и однозначны.

Из руководства по Bash:

${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 экранирование строк" и т. д., чтобы привлечь внимание к теме экранирования строк с одинарными кавычками.

Оцените материал
Добавить комментарий

Капча загружается...