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


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.