Сценарий оболочки - удалить первую и последнюю кавычку (") из переменной

225

Ниже приведен фрагмент сценария оболочки из более крупного сценария. Он удаляет кавычки из строки, содержащейся в переменной. Я делаю это с помощью sed, но эффективно ли это? Если нет, то каков эффективный путь?

#!/bin/sh

opt="\"html\\test\\\""
temp=`echo $opt | sed 's/.\(.*\)/\1/' | sed 's/\(.*\)./\1/'`
echo $temp
user1263746
источник
Я бы предложил использовать sed "s/^\(\"\)\(.*\)\1\$/\2/g" <<<"$opt". Этот синтаксис удалит qoutes только тогда, когда есть совпадающая пара.
Джон Смит
@JohnSmith Мне также нужно автоматически экранировать кавычки в сценарии оболочки, но мне нужно делать это независимо от того, совпадают они или нет, поэтому я, вероятно, не буду использовать то выражение, которое вы опубликовали.
Пизис
Если вы нашли этот вопрос, просто пытаясь удалить все кавычки, посмотрите этот ответ: askubuntu.com/a/979964/103498 .
Гордон Бин

Ответы:

268

Существует более простой и эффективный способ, использующий встроенную функцию удаления префикса / суффикса оболочки:

temp="${opt%\"}"
temp="${temp#\"}"
echo "$temp"

${opt%\"}удалит суффикс "(экранированный с обратной косой чертой для предотвращения интерпретации оболочки).

${temp#\"}удалит префикс "(экранированный с обратной косой чертой для предотвращения интерпретации оболочки).

Еще одним преимуществом является то, что он будет удалять окружающие цитаты, только если есть окружающие цитаты.

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

Используя sed:

echo "$opt" | sed -e 's/^"//' -e 's/"$//'

(Улучшенная версия, как указано в jfgagne, избавление от эха)

sed -e 's/^"//' -e 's/"$//' <<<"$opt"

Таким образом, он заменяет ведущий "ни с чем, и трейлинг "тоже ни с чем. В том же вызове (нет необходимости передавать и запускать другой sed. Используя -eвы можете иметь несколько текстовых обработок).

huelbois
источник
14
Вы можете избавиться от трубы с помощью раствора sed -e 's/^"//' -e 's/"$//' <<< $opt.
jfg956
1
Это может привести к неправильному поведению, если строка не имеет начального и конечного символа кавычки. Любые предложения для обработки этого изящно?
jsears
Чтобы обрабатывать только совпадающие внешние кавычки, см. Ответ @Joachim Pileborg
jsears
1
@ jsears А? Это специально обрезает один с самого начала, если он есть, и один с конца, если он есть. Если вы не хотите удалять, если нет обоих; да, можно использовать одно sedрегулярное выражение или подстановку переменной можно заключить в case $opt in '"'*'"') ... do it ... ;; esac
какую-
2
Вы можете избежать нескольких выражений, используяsed 's/^"\|"$//g'
tzrlk
287

Используйте tr для удаления ":

 echo "$opt" | tr -d '"'

Примечание . При этом удаляются все двойные кавычки, а не только начальные и конечные.

wieczorek1990
источник
16
Это не то, что запрашивал OP, поскольку он также удаляет все кавычки, а не только ведущие и конечные.
Ленар Хойт
19
Хотя я не отвечаю на OP явно, это решает для меня, потому что есть только двойные кавычки в начале и конце "/ path / file-name". Там нет встроенных двойных кавычек. +1
WinEunuuchs2Unix
6
Это решение будет тем, что хотят многие люди. Во многих случаях сценарии могут легко перевести работоспособные данные в строку, заключенную в кавычки.
Шадониня
2
Элегантный и избавил меня от гораздо больше времени отладки проб и ошибок. Спасибо.
Скотт Уэйд
Это то, что в идеале нужно, и поэтому у него больше голосов, чем принятого ответа.
apurvc
38

Это удалит все двойные кавычки.

echo "${opt//\"}"
Стивен Пенни
источник
1
Но сломается с сбежавшими кавычками, например, Don't remove this \" quote. :-(
gniourf_gniourf
Это расширение Bash, поэтому не применимо для сценария оболочки в целом. (Вопрос двусмысленный относительно того, важно ли это или нет. Посетители, которые находят это в Google, могут искать решение POSIX.)
tripleee
Совершенство! Именно то, что мне было нужно. Мне нравятся такие вопросы, которые дают вам множество ответов, а не только то, что запросил ОП. Драгоценные камни находятся в непринятых ответах!
dlite922
Боюсь, что OP хочет что-то, что удаляет только ведущие / конечные кавычки и сохраняет экранированные.
Фернандо Пас
36

Существует простой способ использования xargs :

> echo '"quoted"' | xargs
quoted

xargs использует echo в качестве команды по умолчанию, если команда не указана, и удаляет кавычки из входных данных. Смотрите, например, здесь .

user1587520
источник
echo '"quoted"' | xargs -> quoted
Киб
1
Это работает, но только для четного числа кавычек в строке. Если есть нечетное число, оно генерирует ошибку.
Джеймс Шиви
21

Вы можете сделать это только одним звонком sed:

$ echo "\"html\\test\\\"" | sed 's/^"\(.*\)"$/\1/'
html\test\
Какой-то программист чувак
источник
19

Кратчайший путь - попробуйте:

echo $opt | sed "s/\"//g"

Он фактически удаляет все "s (двойные кавычки) из opt(действительно ли будет больше двойных кавычек, кроме как в начале и в конце, хотя? Так что это на самом деле то же самое, и намного более кратко ;-))

Dr.Kameleon
источник
4
Если вы хотите удалить все двойные кавычки, то еще лучше использовать: "$ {opt // \" /} ". Нет канала, нет подоболочки ... И учтите, что если у вас есть пробелы в opt, вы можете потерять Всегда указывайте переменные вроде: echo "$ opt"
huelbois
Что ж, переменная в основном считывает путь DocumentRoot из файла конфигурации httpd, поэтому я не думаю, что может быть случай, когда в строке может быть символ кавычки. И этот сед гораздо аккуратнее и эффективнее .... Спасибо!
user1263746
16

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

$ echo '{"foo": "bar"}' | jq '.foo'
"bar"

$ echo '{"foo": "bar"}' | jq -r '.foo'
bar
брюзга
источник
Я использую, jqно обратите внимание, что это не работает, если JQ также выводит вывод ASCII с -a(это ошибка на стороне JQ)
Может Poyrazoğlu
yqТакже есть -rопция:yq -r '.foo' file.yml
Глеб Бабий
12

Обновить

Простой и элегантный ответ из Разбор одинарных и двойных кавычек в строке с использованием только команд bash / standard Linux :

BAR=$(eval echo $BAR) полоски цитаты из BAR .

================================================== ===========

Основываясь на ответе Хуэйбуа, после многих проб и ошибок я придумал эту функцию:

function stripStartAndEndQuotes {
    cmd="temp=\${$1%\\\"}"
    eval echo $cmd
    temp="${temp#\"}"
    eval echo "$1=$temp"
}

Если вы не хотите ничего распечатывать, вы можете передать /dev/null 2>&1 .

Использование:

$ BAR="FOO BAR"
$ echo BAR
"FOO BAR"
$ stripStartAndEndQuotes "BAR"
$ echo BAR
FOO BAR
Джонатан Лин
источник
1
Хотя мне действительно нравятся простые и элегантные, я думаю, что стоит заметить, что eval не просто обрабатывает двойные кавычки, а фактически оценивает их как строку кода. Поэтому этот метод может дать неожиданные результаты, когда BAR содержит другие последовательности, которые могут быть заменены оболочкой (например, BAR = \ 'abc \' или BAR = ab \ 'c или BAR = a \ $ b, или BAR = a \ $ (ls *))
MaxP
11

Самое простое решение в Bash:

$ s='"abc"'
$ echo $s
"abc"
$ echo "${s:1:-1}"
abc

Это называется раскрытием подстроки (см. Руководство по Gnu Bash и поиск ${parameter:offset:length}). В этом примере она берет подстроку sначиная с позиции 1 и заканчивая второй последней позицией. Это связано с тем, что если lengthэто отрицательное значение, оно интерпретируется как обратное смещение от конца parameter.

Hiro.Protagonist
источник
отрицательная длина поддерживается bash v4.2
mr.spuratic
8

Это самый дискретный способ без использования sed:

x='"fish"'
printf "   quotes: %s\nno quotes:  %s\n" "$x" "${x//\"/}"

Или

echo $x
echo ${x//\"/}

Вывод:

   quotes: "fish"
no quotes:  fish

Я получил это из источника .

nimig18
источник
Это удалит кавычки из строки, а также окружающие ее.
jsears
Помимо комментариев, это идентично ответу @ StevenPenny от 2012 года .
tripleee
3

Есть еще один способ сделать это. Подобно:

echo ${opt:1:-1}
DevilTour
источник
2

Моя версия

strip_quotes() {
    while [[ $# -gt 0 ]]; do
        local value=${!1}
        local len=${#value}
        [[ ${value:0:1} == \" && ${value:$len-1:1} == \" ]] && declare -g $1="${value:1:$len-2}"
        shift
    done
}

Функция принимает имена переменных и удаляет кавычки. Он удаляет только совпадающую пару ведущих и конечных кавычек. Он не проверяет, экранирует ли конечная кавычка (предшествует\ сам экранирование).

По моему опыту, такие строковые служебные функции общего назначения, как эта (у меня есть их библиотека), наиболее эффективны при непосредственном манипулировании строками, без использования какого-либо сопоставления с образцом и, особенно, при создании каких-либо вложенных оболочек или при вызове каких-либо внешних инструментов, таких как sed, awkили grep.

var1="\"test \\ \" end \""
var2=test
var3=\"test
var4=test\"
echo before:
for i in var{1,2,3,4}; do
    echo $i="${!i}"
done
strip_quotes var{1,2,3,4}
echo
echo after:
for i in var{1,2,3,4}; do
    echo $i="${!i}"
done
Гена Павловский
источник
0

Я знаю, что это очень старый вопрос, но вот еще один вариант sed, который может кому-то пригодиться. В отличие от некоторых других, он заменяет только двойные кавычки в начале или в конце ...

echo "$opt" | sed -r 's/^"|"$//g'
user1751825
источник