Çift tırnak içinde çift tırnaktan nasıl kaçabilirim?


287

Bash'deki bir çift dizenin içindeki çift tırnaklardan nasıl kaçabilirim?

Örneğin, kabuk komut dosyamda

#!/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 '\"'Doğru kaçmak için çift tırnak ile alamıyorum . Değişkeni kullanmak için tek tırnak kullanamıyorum çünkü değişken kullanmak istiyorum $dbtable.




2
@kenorb Bu sorunun bir kopyası gibi görünmüyor ...
Mark


@Daenyth Bu, son kullanıcıların erişmesini beklediğiniz komut türü değildir. Toplu yükleme komut dosyaları genellikle çalıştırılır üzerinde (örneğin sistem yöneticileri veya geliştiriciler gibi) güvenilir kullanıcı tarafından sunucuya. Evet, son kullanıcılar değerini kontrol ederse $dbtablebir risk söz konusudur. Son kullanıcılar verilerini yüklemek için genellikle bir makineye SSH kullanmadığı için bu çok nadirdir.
jpmc26

Yanıtlar:


285

Ters eğik çizgi kullanın:

echo "\""     # Prints one " character.

9
Çalışmıyor. x=ls; if [ -f "$(which "\""$x"\"")" ]; then echo exists; else echo broken; fi;kırılmış verir ... [ -f "$(which $x)" ]; ...veya iyi ... [ -f $(which "$x") ]; ...çalışır. Bir boşluk veya başka bir özel karakter ile herhangi bir şey verildiğinde $xveya ortaya çıktığında sorunlar ortaya çıkacaktır $(which "$x"). Geçici çözüm sonucu tutmak için bir değişken kullanıyor which, ama bash gerçekten bir teklif kaçmak için aciz veya yanlış bir şey mi yapıyorum?
Luc

Aşağıdaki bir değişken grep -oh "\"\""$counter"\""\w*" olduğu bir bash sözdiziminin bir parçası olarak kullanmaya çalışıyorum $counter. herhangi bir düşünce sevmez
Jay D

82

Kabuktan alıntılardan kaçmanın basit bir örneği:

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

Zaten açık olanı ( ') bitirerek , kaçanı ( ) yerleştirip \'başka bir tane ( ') açarak yapılır .

Alternatif:

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

Zaten açılmış bir ( ') öğesini bitirerek , başka bir alıntıya ( "'") bir teklif koyarak ve başka bir ( ') açarak yapılır .

Daha fazla örnek: Tek tırnaklı dizelerdeki tek tırnaklardan kaçma


1
Sh -c "echo '{" key ":" value "}'" ve hatta sh -c "echo '{' '"' 'key' '"' ':' '"' 'değer' '"" '}' "anahtar ve değer kelimelerini çift tırnak içine alma çabasıyla, ancak her iki durumda da {key: value}
Igor Yagolnitser

1
Bu, çift tırnak için gereksiz yere karmaşık görünüyor: Peter cevabında olduğu gibi echo "abc\"abc"üretmek için yeterli abc"abc.
divenex

2
Gerçekten bu basit örnekte, ancak karmaşık iç içe tırnak söz konusu olduğunda, bunu yapmak gerekli olabilir ve @ kenorb'un örneği bu davalarla nasıl başa çıkacağımı anlamama yardımcı oldu.
prosoitolar

63

Bu eski sorunun neden Bash etiketli listelerinde bugün ortaya çıktığını bilmiyorum, ancak gelecekteki araştırmacılar için yankılamanız gereken karakterlerin ASCII kodlarını kullanarak kaçmayı önleyebileceğinizi unutmayın.

Misal:

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

\x22çift ​​tırnak işaretleri ve \x27tek tırnak işaretleri için ASCII kodudur (onaltılık) . Benzer şekilde herhangi bir karakteri yankılayabilirsiniz.

Yukarıdaki dizeyi ters eğik çizgilerle yankılamaya çalışırsak, dağınık iki sıra ters eğik yankıya ihtiyacımız olacak ... :)

Değişken ataması için bu eşdeğerdir:

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

Değişken zaten başka bir program tarafından ayarlanmışsa, sed veya benzeri araçlarla çift / tek tırnak uygulayabilirsiniz.

Misal:

 $ 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, ~ / .profile dosyasına bir PS1 değişkeni ekleme sorununu çözdü 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
İşte cevap! Seni seviyorum efendim.
Miguel Rojas Cortés

28

Bash, dizeleri bitişik olarak yerleştirmenize izin verir ve sadece birbirine yapıştırılırlar.

Yani bu:

$ echo "Hello"', world!'

üretir

Hello, world!

İşin püf noktası, tek ve çift tırnaklı dizeler arasında gerektiği gibi geçiş yapmaktır. Ne yazık ki, çabuk dağınık hale geliyor. Örneğin:

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

üretir

I like to use "double quotes" sometimes

Örneğinizde, böyle bir şey yapardım:

$ 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

Aşağıdaki çıktıyı üreten:

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

Burada neler olduğunu görmek zor, ancak Unicode alıntılarını kullanarak açıklama ekleyebilirim. Aşağıdakiler bash'de çalışmaz - sadece örnekleme amaçlıdır:

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

Yukarıdaki "" "gibi alıntılar bash tarafından yorumlanacaktır. Like tırnaklar " 'sonuçta ortaya çıkan değişken ile sonuçlanır

Daha önceki örneğe aynı tedaviyi verirseniz, şöyle görünür:

$ echoI like to use' "double quotes"' sometimes


4
Oof ... bu çirkin şeyler.
Sihirli Ahtapot Urn

17

Check out printf ...

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

Printf kullanmadan

echo -e $mystr

Çıktı: "merhaba" de

Printf kullanma

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

Çıktı: \ "merhaba \" de


2
Not printfgibi, hem de daha fazla karakter kaçar ', (ve)
David Pärsson

printf %qiçin hazır eval, biçimlendirilmemiş dizeler oluşturur echo -e.
Charles Duffy

2
'Nin yararsız bir kullanımıprintf ile sarılması için hiçbir sebep yoktur . Her iki örnekte de alıntılar bozuk. Doğru düzeltme, değişkeni çift tırnak içine almaktır. echo
üçlü

15

Çift tırnak karakterini değişken olarak saklayın:

DQT = '"'
echo "Çift tırnak içine alınmış bir çift dize içinde $ {dqt} X $ {dqt}"

Çıktı:

Çift tırnak içine alınmış bir dize içinde çift tırnak "X"

39
Bash gerçekten en kötü dil
Andy Ray

@ 12oclocker, cevabınız kusursuz: D! Özellikle "sed" komutuyla kullanırken günümü kurtardı!
Artanis Zeratul

11

$ "String" kullanın.

Bu örnekte,

dbload = $ "\" '\ n' \ "IGNORE 1 LINES" İLE SONLANDIRILAN ',' \ '' TARAFINDAN SONLANDIRILAN "$ dbtable FIELDS tabloya yerel veri \" 'gfpoint.csv' \ "yükleyin

Not ( kılavuz sayfasından ):

Dolar işareti ($ "string") olan çift tırnaklı bir dize, dizenin geçerli yerel ayara göre çevrilmesine neden olur. Geçerli yerel ayar C veya POSIX ise, dolar işareti yok sayılır. Dize çevrilir ve değiştirilirse, değiştirme çift tırnak içine alınır.


3
Güzel, bunu bilmiyordum.
David Kierans

-5

"\"Kaçmak için çift tırnaktan önce ekleyin ,\

#! /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: Neden bir cshsoruya cevap gönderiyorsunuz bash? İkisi tamamen farklı ve uyumsuz.
üçlü
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.