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


225

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

#!/bin/sh

opt="\"html\\test\\\""
temp=`echo $opt | sed 's/.\(.*\)/\1/' | sed 's/\(.*\)./\1/'`
echo $temp

Я бы предложил использовать 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вы можете иметь несколько текстовых обработок).


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 '"'

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


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 в качестве команды по умолчанию, если команда не указана, и удаляет кавычки из входных данных. Смотрите, например, здесь .


echo '"quoted"' | xargs -> quoted
Киб

1
Это работает, но только для четного числа кавычек в строке. Если есть нечетное число, оно генерирует ошибку.
Джеймс Шиви


19

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

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

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


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.


отрицательная длина поддерживается 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

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


Это удалит кавычки из строки, а также окружающие ее.
jsears

Помимо комментариев, это идентично ответу @ StevenPenny от 2012 года .
tripleee


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'
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.