2010-09-30 21 views
147

Czy ktoś może mi pokazać, jak uniknąć podwójnego cudzysłowu w podwójnym ciągu w bash?Jak uniknąć podwójnego cudzysłowu wewnątrz podwójnego cudzysłowu?

Na przykład w moim skrypcie

#!/bin/bash 

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

nie mogę dostać ENCLOSED PRZEZ \" z podwójnym cytując ucieczce prawidłowo. Nie mogę użyć pojedynczego cudzysłowu dla mojej zmiennej, ponieważ chcę użyć zmiennej $dbtable.

+45

Należy zapoznać się z koncepcją [SQL injection] (http: // en. wikipedia.org/wiki/SQL_injection) zanim zaczniesz pisać kod taki jak ten. – Daenyth

+1

Zobacz także http://mywiki.wooledge.org/BashFAQ/050 –

+0

możliwy duplikat [Escaping pojedynczych cudzysłowów w ciągu cudzysłowów] (http://stackoverflow.com/questions/1250079/escaping-single-quotes- w ciągu pojedynczych znaków) – kenorb

Odpowiedz

170

pomocą ukośnika:

echo "\""  # Prints one " character. 
+3

Nie działa. 'x = ls; jeśli [-f "$ (co" \ "" $ x "\" ")"]; wtedy echo istnieje; inaczej rozbite echo; fi; 'daje zepsute, podczas gdy' ... [-f "$ (co $ x)"]; ... 'lub' ... [-f $ (które "$ x")]; ... "działa dobrze. Problemy pojawiłyby się, gdy '$ x' lub wynik' $ (który "$ x") 'daje cokolwiek z spacją lub innym specjalnym znakiem. Obejście polega na użyciu zmiennej do przechowywania wyniku 'co', ale czy bash naprawdę nie jest w stanie uniknąć cytatu, czy też robię coś nie tak? – Luc

+0

Próbuję użyć następującego 'grep -oh" \ "\" "licznik $" \ "" \ w * "' jako część składni bash, gdzie w '$ counter' jest zmienną. nie lubi żadnych myśli –

10

Wyjazd printf ...

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

Bez użycia printf

echo -e $mystr 

wyjście: powiedzieć "cześć"

Korzystanie printf

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

wyjście say \ "hi \"

+1

Zauważ, że 'printf' wymyka się również większej liczbie znaków, takich jak' ',' ('i') ' –

+0

' printf% q' generuje łańcuchy gotowe do 'eval', niesformatowane dla 'echo -e'. –

+2

Nie ma powodu, aby owijać 'printf' [bezużytecznym użyciem' echo'] (http://www.iki.fi/era/unix/award.html#echo). Oba przykłady zepsowały cytowanie. Poprawną poprawką jest podwójne cytowanie zmiennej. – tripleee

35

Prosty przykład ucieczki cytaty w łupinach:

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

to się robi kończąc już otwarty jeden (') umieszczenie jednego Escaped (\'), a następnie otwarcie kolejnego (').

Alternatywnie:

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

Zrobione kończąc już otwarty jeden ('), umieszczając ofertę w innym cytatem ("'"), a następnie otwierając kolejną (').

Więcej przykładów: Escaping single-quotes within single-quoted strings

+1

Próbowałem sh -c "echo" {"klucz": "wartość"} "" a nawet sh -c "echo" {"" "klucz" "" ":" "" "wartość" "" ''} '' w celu zamknięcia słów kluczowych i wartości w podwójnych cudzysłowach, ale w obu przypadkach dostałem {key: value} –

17

Bash pozwala na umieszczenie w sąsiedztwie ciągów, a oni po prostu skończyć sklejone ze sobą.

Więc tak:

$ echo "Hello"', world!' 

produkuje

Hello, world! 

Sztuką jest, aby przełączać pomiędzy pojedynczych i podwójnych cudzysłowów w miarę potrzeb. Niestety, szybko staje się bardzo brudny.Na przykład:

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

produkuje

I like to use "double quotes" sometimes 

W przykładzie, zrobiłbym to coś takiego:

$ 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 

która produkuje następujące dane wyjściowe:

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

Trudno, aby zobaczyć, co się tutaj dzieje, ale mogę opisywanie go za pomocą cytatów Unicode. Poniższa nie będzie działać w bash - to tylko dla ilustracji:

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

Cytaty takie jak "" "w powyższym będą interpretowane przez bash. Cytaty takie jak " ' znajdą się w wynikowej zmiennej.

Jeśli dam takie samo traktowanie wcześniejszym przykładzie wygląda to tak:

$ echoI like to use"double quotes"sometimes

3

korzystanie Marka $ "string".

W tym przykładzie byłoby,

DBLoad = $ "dane obciążenie lokalnego plik_we \" 'gfpoint.csv' \”na stół $ POLA DbTable zakończone przez '' ENCLOSED BY„\” 'Linie zakończone bY \ " '\ n' \" IGNORUJ 1 wierszach”

Note (od man page):

podwójnie cytowany łańcuch poprzedzony znakiem dolara ($ "string") spowoduje, że łańcuch zostanie przetłumaczony zgodnie do bieżącego locale. Jeśli bieżącym locale jest C lub POSIX, znak dolara jest ignorowany. Jeśli łańcuch jest tłumaczony i zastępowany, zamiennik jest podwójnie cytowany.

-4

dodać "\" przed podwójny cudzysłów, aby go uniknąć, zamiast \

#! /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 
+2

Downvote: Dlaczego publikujesz odpowiedź 'csh' na pytanie' bash'? Oba są całkowicie odrębne i niekompatybilne. – tripleee

20

Nie wiem, dlaczego ten stary problem pojawił się dzisiaj w bash oznaczone ofert, ale na wszelki wypadek dla przyszłych badaczy , należy pamiętać, że można uniknąć ucieczki, używając kodów ASCII znaków, które należy powtórzyć. przykład:

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

\x22 jest kodem ASCII (w heksanie) dla cudzysłowach i \x27 do apostrofami. Podobnie możesz wywołać echo dowolnego znaku.

Przypuszczam, że jeśli spróbujemy powtórzyć powyższy ciąg z ukośniki, musimy brudny dwa rzędy odwrotnym ukośnikiem echo ... :)

Dla przypisania zmiennej to jest równoważne:

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

Jeśli zmienna jest już ustawiona przez inny program, możesz nadal stosować podwójne/pojedyncze cudzysłowy z narzędziem sed lub podobnym. Przykład:

$ 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. 
+0

+1, ponieważ rozwiązał problem z dodaniem zmiennej PS1 do ~/.profile "echo" eksport 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' –

+2

powinno to być prawdopodobnie oznaczone jako odpowiedź. – qodeninja

3

Store podwójny charakter cytat jako zmiennej:

 
dqt='"' 
echo "Double quotes ${dqt}X${dqt} inside a double quoted string" 

wyjściowa:

 
Double quotes "X" inside a double quoted string 
Powiązane problemy