Як я можу уникнути подвійної цитати всередині подвійних цитат?


286

Як я можу уникнути подвійних лапок всередині подвійного рядка в Bash?

Наприклад, у моєму сценарії оболонки

#!/bin/bash

dbload="load data local infile \"'gfpoint.csv'\" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY \"'\n'\" IGNORE 1 LINES"

Я не можу ENCLOSED BY '\"'з подвійною цитатою вирватися правильно. Я не можу використовувати одинарні лапки для своєї змінної, тому що я хочу використовувати змінну $dbtable.




2
@kenorb Не схоже на копію цього питання ...
Марк


@Daenyth Це не той тип команд, до якого очікують, що кінцеві користувачі матимуть доступ. Сценарії масового завантаження зазвичай виконуються на сервері довіреними користувачами (наприклад, системними адміністраторами або розробниками). Так, якщо кінцеві користувачі контролюють значення $dbtable, існує ризик. Це було б дуже рідко, оскільки кінцеві користувачі, як правило, SSH не завантажують у машину для завантаження своїх даних.
jpmc26

Відповіді:


285

Використовуйте зворотний нахил:

echo "\""     # Prints one " character.

9
Не працює. x=ls; if [ -f "$(which "\""$x"\"")" ]; then echo exists; else echo broken; fi;дає зламаний тоді, ... [ -f "$(which $x)" ]; ...або ... [ -f $(which "$x") ]; ...працювати добре. Проблеми виникають тоді, коли будь-який $xабо результат $(which "$x")дає щось із пробілом чи іншим особливим характером. Для вирішення результату використовується змінна which, але невже баш не може уникнути цитати чи я щось не так роблю?
Люк

Я намагаюся використовувати наступне grep -oh "\"\""$counter"\""\w*" як частину синтаксису bash, де в $counter- це змінна. це не любить жодних думок
Jay D

82

Простий приклад уникнення лапок в оболонці:

$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc

Це робиться, закінчивши вже відкритий ( '), розмістивши втечене ( \'), а потім відкривши ще одне ( ').

Як варіант:

$ echo 'abc'"'"'abc'
abc'abc
$ echo "abc"'"'"abc"
abc"abc

Це робиться, закінчивши вже відкритий один ( '), помістивши цитату в іншу цитату ( "'"), а потім відкривши ще одну ( ').

Більше прикладів: уникнення одиночних лапок у рядках з одним цитуванням


1
Я спробував sh -c "echo" {"key": "value"} "" і навіть sh -c "echo" {'' "'key' '" "": "" "' value ''" ' '}' ", намагаючись укласти подвійні лапки у слова та значення, але в обох випадках я отримав {ключ: значення}
Ігор Ягольницер,

1
Це видається непотрібним для подвійних цитат: echo "abc\"abc"достатньо для отримання відповіді, abc"abcяк у відповіді Петра.
divenex

2
В цьому простому прикладі, але в складних випадках вкладених цитат, це може знадобитися, і приклад @ kenorb допоміг мені розібратися, як вчинити з цими справами.
prosoitos

63

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

Приклад:

 echo -e "This is \x22\x27\x22\x27\x22text\x22\x27\x22\x27\x22"
 This is "'"'"text"'"'"

\x22- код ASCII (у шістнадцятковій формі) для подвійних лапок та \x27для одинарних лапок. Точно так само можна повторити будь-якого персонажа.

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

Для призначення змінних це еквівалент:

 $ a=$'This is \x22text\x22'
 $ echo "$a"
 This is "text"

Якщо змінна вже встановлена ​​іншою програмою, ви все ще можете застосувати подвійні / одиничні лапки за допомогою sed або подібних інструментів.

Приклад:

 $ b="Just another text here"
 $ echo "$b"
 Just another text here
 $ sed 's/text/"'\0'"/' <<<"$b" #\0 is a special sed operator
 Just another "0" here #this is not what i wanted to be
 $ sed 's/text/\x22\x27\0\x27\x22/' <<<"$b"
 Just another "'text'" here #now we are talking. You would normally need a dozen of backslashes to achieve the same result in the normal way.

1
+1, оскільки це вирішило проблему додавання змінної PS1 до ~ / .profile echo 'export PS1='\[\033[00;31m\]${?##0}$([ $? -ne 0 ] && echo \x22 \x22)\[\033[00;32m\]\u\[\033[00m\]@\[\033[00;36m\]\h\[\033[00m\][\[\033[01;33m\]\d \t\[\033[00m\]] \[\033[01;34m\]\w\n\[\033[00m\]$( [ ${EUID} -ne 0 ] && echo \x22$\x22 || echo \x22#\x22 ) '' >> ~/.profile
Yassine ElBadaoui

1
Це відповідь! Я люблю тебе, сер.
Мігель Рохас Кортес

28

Bash дозволяє розміщувати рядки поруч, і вони просто закінчуються склеюванням.

Отже це:

$ echo "Hello"', world!'

виробляє

Hello, world!

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

$ echo "I like to use" '"double quotes"' "sometimes"

виробляє

I like to use "double quotes" sometimes

У вашому прикладі я зробив би це приблизно так:

$ dbtable=example
$ dbload='load data local infile "'"'gfpoint.csv'"'" into '"table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '"'"'"' LINES "'TERMINATED BY "'"'\n'"'" IGNORE 1 LINES'
$ echo $dbload

який дає такий вихід:

load data local infile "'gfpoint.csv'" into table example FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY "'\n'" IGNORE 1 LINES

Важко зрозуміти, що тут відбувається, але я можу зазначити це за допомогою котировок Unicode. Наступне не буде працювати в bash - це лише для ілюстрації:

dbload=' load data local infile "' 'gfpoint.csv'' " into' table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '' "' ' LINES' TERMINATED BY "' '\n'' " IGNORE 1 LINES' ' ' ' ' ' ' ' ' '

Цитати на зразок "" "у наведеному вище будуть інтерпретуватися bash. Цитати на зразок " 'закінчуються в отриманій змінній.

Якщо я даю те саме лікування на попередньому прикладі, це виглядає приблизно так:

$ echo« I like to use» « "double quotes"» « sometimes»


4
На жаль ... це якісь потворні речі.
Чарівний восьминога

17

Перевірте printf ...

#!/bin/bash
mystr="say \"hi\""

Без використання printf

echo -e $mystr

Вихід: сказати "привіт"

Використання printf

echo -e $(printf '%q' $mystr)

Вихід: скажіть \ "привіт \"


2
Зауважте, що також printfуникає більше персонажів, таких як ', (і)
Девід Пярссон

printf %qстворює рядки, готові до eval, не відформатовані для echo -e.
Чарльз Даффі

2
Немає жодних підстав для завершення роботи printfз марним використаннямecho . Обидва ваші приклади порушили цитування. Правильне виправлення - подвійне цитування змінної.
трійка

15

Збережіть символ подвійної лапки як змінний:

dqt = '"'
echo "Подвійні котирування $ {dqt} X $ {dqt} всередині подвійного ряду, що цитується"

Вихід:

Подвійні лапки "X" всередині подвійного ряду, що цитується

39
Баш справді - найгірша мова
Енді Рей

@ 12oclocker, ваша відповідь є дурною: D! спеціально при використанні команди "sed" це врятувало мені день!
Артаніс Зератул

11

Скористайтеся $ "string".

У цьому прикладі було б,

dbload = $ "завантажувати дані локального infile \" 'gfpoint.csv' \ "у таблицю $ dbtable ПОЛЯ, ЗАВЕРШЕНІ", "ЗАКРИТИ" \ "" ЛІНІЇ, ЗАКРІНЕНІ \ "" \ n "\" IGNORE 1 LINES "

Примітка (зі сторінки чоловіка ):

Рядок з подвійним котируванням, який передує знаку долара ($ "string"), призведе до перекладу рядка відповідно до поточного локалу. Якщо поточний локал - C або POSIX, знак долара ігнорується. Якщо рядок переведено та замінено, заміна подвійно цитується.


3
Гарно, не знав цього.
David Kierans

-5

Додайте "\"перед подвійною цитатою, щоб уникнути цього, а не\

#! /bin/csh -f

set dbtable = balabala

set dbload = "load data local infile "\""'gfpoint.csv'"\"" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '"\""' LINES TERMINATED BY "\""'\n'"\"" IGNORE 1 LINES"

echo $dbload
# load data local infile "'gfpoint.csv'" into table balabala FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY "''" IGNORE 1 LINES

6
Downvote: Чому ви публікуєте cshвідповідь на bashзапитання? Два цілком виразні і несумісні.
трійка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.