2012-03-16 26 views
98

Poniżej znajduje się fragment skryptu powłoki z większego skryptu, który usuwa cudzysłowy z łańcucha będącego w posiadaniu zmiennej. Robię to za pomocą sed, jest to skuteczne, jeśli nie to co jest skutecznym sposobemSkrypt powłoki - usuń pierwszy i ostatni cudzysłów (") ze zmiennej

#!/bin/sh 

opt="\"html\\test\\\"" 
temp=`echo $opt | sed 's/.\(.*\)/\1/' | sed 's/\(.*\)./\1/'` 
echo $temp 
+0

I sugerowałyby przy użyciu 'sed "s/^ \ (\" \) \ (. * \) \ 1 \ $/\ 2/g "<<<" $ opt Ta składnia usunie qoute tylko wtedy, gdy istnieje pasująca para: –

+0

@JohnSmith Muszę też automatycznie ukrywać cudzysłowy w skrypcie powłoki, ale muszę to zrobić bez względu na to, czy pasują, czy nie, więc prawdopodobnie nie będę używał to wyrażenie, które opublikowałeś – Pysis

Odpowiedz

133

jest bardziej prosty i skuteczny, przy użyciu prefiksu rodzimy powłoki/funkcja usuwania sufiksu:

temp="${opt%\"}" 
temp="${temp#\"}" 
echo "$temp" 

$ {opt% \ "} usunie przyrostek" (uciekł z backslash aby zapobiec interpretacji shell)

$ {temp # \ "} usunie prefiks" (uciekł z backslash do zapobiec interpretacji powłoki)

Kolejną zaletą jest to, że usuwa otaczające cytaty tylko wtedy, gdy są w pobliżu cytaty.

BTW, twoje rozwiązanie usuwa zawsze pierwszą i ostatnią postać, niezależnie od tego, czym one są (oczywiście, jestem pewien, że znasz swoje dane, ale zawsze lepiej mieć pewność, co usuwasz).

Korzystanie sed:

echo "$opt" | sed -e 's/^"//' -e 's/"$//' 

(ulepszona wersja, jak wskazano jfgagne, pozbycie echo)

sed -e 's/^"//' -e 's/"$//' <<<"$opt" 

Więc Zastępuje on wiodącą "z niczego, i na końcu" z niczego także. W tej samej inwokacji (nie trzeba potokować i uruchomić innego sed, używając opcji -e możesz mieć wiele procesów przetwarzania tekstu).

+9

Możesz pozbyć się rury w roztworze sed za pomocą 'sed -e 's/^" //' -e 's/"$ //' < << $ opt'. – jfg956

+1

Może to źle działać, ciąg znaków nie ma ani znaku wiodącego, ani końcowego znaku cudzysłowu. z wdziękiem? – jsears

+0

Aby obsłużyć tylko dopasowane cudzysłowy zewnętrzne, zobacz odpowiedź @Joachim Pileborg – jsears

13

można to zrobić tylko jeden telefon do sed:?

$ echo "\"html\\test\\\"" | sed 's/^"\(.*\)"$/\1/' 
html\test\ 
+0

+1 tylko dla obsługi najbardziej zewnętrznych cytatów – patthoyts

7

Najkrótsza droga wokół - spróbuj:

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

To faktycznie usuwa wszystkich "(cudzysłów) z opt (są tam naprawdę będzie żadnych więcej cudzysłowy inne niż na początku i na końcu chociaż? tak, to właściwie to samo, i znacznie bardziej zwięzły ;-))

+3

Jeśli chcesz usunąć wszystkie podwójne cudzysłowy, to jeszcze lepiej użyć: "$ {opt // \" /} ". Bez rury, bez podpowłoki ... I pamiętaj, że jeśli masz spacje w opt, możesz Odrzucaj zawsze zmienne takie jak: echo "$ opt" – huelbois

+0

Cóż, zmienna w zasadzie odczytuje ścieżkę DocumentRoot z pliku konfiguracyjnego httpd, więc nie sądzę, że może istnieć przypadek, w którym może być cytowany znak w łańcuchu. to sed jest o wiele ładniejsze i wydajniejsze ... Dzięki! – user1263746

+0

Też tak pomyślałem. Nie ma za co .-) –

22

Spowoduje to usunięcie wszystkich cudzysłów.

echo "${opt//\"}" 
+0

Ale zerwiesz z wyciętymi cudzysłowami, np. 'Nie usuwaj tego \" cytatu'. ':-(' –

+0

To jest rozszerzenie Bash, więc nie dotyczy ono ogólnie skryptu powłoki (pytanie jest niejednoznaczne, czy jest to ważne, czy też nie, a użytkownicy, którzy znajdują to w Google, mogą szukać rozwiązania POSIX.) – tripleee

123

Użyj tr, aby usunąć ":

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

Nie jest to tym, o co prosił OP, ponieważ usuwa również wszystkie cytaty, a nie tylko te wiodące i końcowe –

+3

Chociaż nie odpowiadając OP OP wyraźnie to rozwiązuje dla mnie, ponieważ są tylko podwójne cudzysłowy na początku i końcu "/ path/file- name ".Nie ma osadzonych podwójnych cudzysłowów +1 – WinEunuuchs2Unix

3

Czy nie jest to najbardziej dyskretny sposób bez użycia sed?

x='"fish"' 
printf " quotes: %s\nno quotes: %s\n" "$x" "${x//\"/}" 

LUB

echo $x 
echo ${x//\"/} 

wyjściowa:

quotes: "fish" 
no quotes: fish 

mam to od Source

+0

Spowoduje to usunięcie cudzysłowów zarówno z ciągu, jak i otaczających go – jsears

+0

Oprócz komentarza, jest to identyczne z [@ StevenPenny odpowiedź z 2012] (http: // stackoverflow.com/a/10943857/874188). – tripleee

0

moja wersja

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 
} 

Funkcja akceptuje nazwy zmiennych i wycina paski w miejscu. Usuwa tylko pasującą parę początkowych i końcowych cudzysłowów. Nie sprawdza, czy końcowa oferta jest unikana (poprzedzona przez \, która nie jest sama w sobie uciekła).

Z mojego doświadczenia wynika, że ​​takie narzędzie ogólnego przeznaczenia działające w ten sposób (mam ich bibliotekę) jest najbardziej wydajne podczas bezpośredniego manipulowania ciągami, bez użycia żadnego dopasowywania wzorca, a zwłaszcza bez tworzenia żadnych podpowłok lub wywoływania jakichkolwiek narzędzia zewnętrzne, takie jak sed, awk lub 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 
3

Aktualizacja

Prosty i elegancki odpowiedź od https://stackoverflow.com/a/24358387/1161743:

BAR=$(eval echo $BAR) paski cytuje BAR.

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

podstawie odpowiedzi hueybois, w wymyśliłem tej funkcji po wielu prób i błędów:

function stripStartAndEndQuotes { 
    cmd="temp=\${$1%\\\"}" 
    eval echo $cmd 
    temp="${temp#\"}" 
    eval echo "$1=$temp" 
} 

Jeśli nie ma nic wydrukowane, możesz przepchnąć rzeczy do numeru /dev/null 2>&1.

Zastosowanie:

$ BAR="FOO BAR" 
$ echo BAR 
"FOO BAR" 
$ stripStartAndEndQuotes "BAR" 
$ echo BAR 
FOO BAR 
+0

Chociaż bardzo lubię proste i eleganckie, myślę, że warto zauważyć, że eval nie robi tylko podwójnego cytatu trimmi ngs, ale w rzeczywistości jest to linia kodu. Dlatego ta technika może dać nieoczekiwane wyniki, gdy BAR zawiera inne sekwencje, które mogą być podstawiane przez powłokę (np. BAR = \ 'abc \' lub BAR = ab \ 'c lub BAR = a \ $ b, lub BAR = a \ $ \ (ls \ * \)) – MaxP