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


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 Мені також доведеться автоматично уникати лапок в сценарії оболонки, але мені потрібно зробити це, чи вони відповідають, чи ні, тому я, ймовірно, не буду використовувати цей вираз, який ви опублікували.
Pysis

Якщо ви знайшли це запитання, просто бажаючи видалити всі лапки, дивіться цю відповідь: 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"

Таким чином, він замінює ведучого "ні з чим, а трейлінг - "ні з чим теж. У тому ж самому виклику (немає необхідності переводити та запускати інший сед. Використовуючи -eви можете проводити багаторазову обробку тексту).


14
Ви можете позбутися від труби в розчині sed sed -e 's/^"//' -e 's/"$//' <<< $opt.
jfg956

1
Це може неправильно поводитись з тим, що рядок не має як провідного, так і останнього символу цитати. Будь-які пропозиції для поводження з цим витончено?
jsears

Щоб обробляти лише відповідні зовнішні цитати, дивіться відповідь @Joachim Pileborg
jsears

1
@jsears Так? Це спеціально обрізає один із самого початку, якщо такий є, а інший із кінця, якщо такий є. Якщо ви не хочете видаляти, якщо вони не є обома; так, sedможе бути використаний один регулярний вираз, або заміна змінної може бути загорнутий у щось рядокcase $opt in '"'*'"') ... do it ... ;; esac
tripleee

2
Ви можете уникнути численних виразів, скориставшисьsed 's/^"\|"$//g'
tzrlk

287

Використовуйте tr для видалення ":

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

Примітка . Це видаляє всі подвійні лапки, а не лише провідні та відсталі.


16
Про це не вимагала ОП, оскільки вона також вилучає всі котирування, не лише провідні та кінцеві.
Ленар Хойт

19
Хоча явно не відповідаю на ОП, це вирішує для мене, оскільки на початку та в кінці "/ path / file-name" є лише подвійні лапки. Немає вбудованих подвійних лапок. +1
WinEunuuchs2Unix

6
Це рішення буде тим, чого хоче багато людей. У багатьох випадках сценарії можуть легко звести працездатні дані до рядка, оточеного цитатами.
Shadoninja

2
Елегантний і врятував мене від набагато більше часу пробної помилки та налагодження. Дякую.
Скотт Уейд

Саме цього в ідеалі хочеться, і саме тому у нього більше голосів, ніж прийнята відповідь.
apurvc

38

Це видалить усі подвійні лапки.

echo "${opt//\"}"

1
Але зламається з втекли лапками, наприклад, Don't remove this \" quote. :-(
gniourf_gniourf

Це розширення Bash, тому взагалі не застосовується до сценарію оболонки. (Питання неоднозначне, важливо це чи ні. Відвідувачі, які виявили це в Google, можуть шукати рішення POSIX.)
tripleee

Вдосконалення! Саме те, що мені було потрібно. Я люблю такі питання, які дають вам безліч відповідей, а не лише те, що вимагала ОП. Самоцвіти є у неприйнятих відповідях!
dlite922

Я боюся, що ОП хоче щось, що видаляє лише провідні / кінцеві цитати та зберігає ті, що вийшли.
Фернандо Пас

36

Існує простий спосіб використання xargs :

> echo '"quoted"' | xargs
quoted

xargs використовує echo як команду за замовчуванням, якщо жодна команда не передбачена і знімає цитати з вхідних даних. Дивіться, наприклад, тут .


echo '"quoted"' | xargs -> quoted
kyb

1
Це працює, але лише для парної кількості цитат у рядку. Якщо є непарне число, воно генерує помилку.
Джеймс Швай


19

Найкоротший шлях - спробуйте:

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

Це насправді видаляє всі "s (подвійні лапки) з opt(чи справді будуть більше подвійних лапок, окрім як на початку та наприкінці? Хоча це насправді те саме, і набагато коротше ;-))


4
Якщо ви хочете видалити всі подвійні лапки, тоді ще краще використовувати: "$ {opt // \" /} ". Ні труби, ні передплатки ... І будьте уважні, що якщо у вас є пробіли у виборі, ви можете втратити Завжди
цитуйте

Ну, змінна в основному читає шлях DocumentRoot від конфігураційного файлу httpd, тому я не думаю, що може виникнути випадок, коли символ цитата може бути там, у рядку. І ця седла набагато акуратніше і ефективніше .... Дякую!
користувач1263746

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 / стандартні команди Linux :

BAR=$(eval echo $BAR)смужки цитати з BAR.

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

На основі відповіді hueybois я придумав цю функцію після багатьох спроб та помилок:

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

Я знаю, що це дуже давнє запитання, але ось ще одна зміна седу, яка може комусь бути корисною. На відміну від деяких інших, він замінює лише подвійні лапки на початку або в кінці ...

echo "$opt" | sed -r 's/^"|"$//g'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.