Kabuk betiği - bir değişkenten ilk ve son alıntıyı (") kaldır


225

Aşağıda, daha büyük bir komut dosyasından bir kabuk komut dosyasının snippet'i bulunmaktadır. Bir değişken tarafından tutulan dizeden tırnak işaretlerini kaldırır. Sed kullanarak yapıyorum, ama verimli mi? Değilse, etkili yol nedir?

#!/bin/sh

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

Ben kullanmanızı öneririm sed "s/^\(\"\)\(.*\)\1\$/\2/g" <<<"$opt". Bu sözdizimi qoutes'i yalnızca eşleşen bir çift olduğunda kaldırır.
John Smith

@JohnSmith Ben de otomatik olarak bir kabuk komut dosyasındaki tırnak kaçmak zorunda, ama onlar eşleşen ya da değil, bunu yapmak gerekir, bu yüzden muhtemelen ben bu ifade kullandığınız ifade kullanmayacak.
17'de

Tüm soruları kaldırmak istediğinizde bu soruyu bulduysanız , şu yanıta bakın: askubuntu.com/a/979964/103498 .
Gordon Bean

Yanıtlar:


268

Yerel kabuk öneki / soneki kaldırma özelliğini kullanarak daha basit ve daha verimli bir yol vardır:

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

${opt%\"}soneki kaldıracaktır "(kabuk yorumlamasını önlemek için ters eğik çizgi ile kaçtı).

${temp#\"}öneki kaldırır "(kabuk yorumlamasını önlemek için ters eğik çizgiyle kaçar).

Başka bir avantajı, yalnızca tırnak içine alındığında çevresindeki tırnak işaretlerini kaldıracağıdır.

BTW, çözümünüz her zaman ilk ve son karakteri kaldırır, ne olursa olsun (elbette, verilerinizi bildiğinizden eminim, ancak neyi kaldırdığınızdan emin olmak her zaman daha iyidir).

Sed kullanma:

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

(Geliştirilmiş versiyon, jfgagne tarafından gösterildiği gibi, yankıdan kurtuluyor)

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

Bu yüzden "bir önderliği hiçbir şeyle değil, bir öyküyü "de hiçbir şeyle değiştirmez. Aynı çağrıda (başka bir sed'i başlatmaya ve başlatmaya gerek yoktur. Kullanarak -ebirden fazla metin işleme yapabilirsiniz).


14
Sed solüsyonundaki borudan kurtulabilirsiniz sed -e 's/^"//' -e 's/"$//' <<< $opt.
jfg956 17:12

1
Bu, dizenin hem önde hem de sondaki tırnak karakterine sahip olmamasına yol açabilir. Bunu incelikle işlemek için herhangi bir öneriniz var mı?
jsears

Sadece eşleşen dış tırnak işlemek için @Joachim Pileborg
jsears

1
@jsears Huh? Bu özellikle bir tane varsa başından, biri varsa sondan keser. Her ikisi de mevcut olmadığı sürece kaldırmak istemiyorsanız; evet, tek bir sednormal ifade kullanılabilir veya değişken ikame bir şey satırına sarılabilircase $opt in '"'*'"') ... do it ... ;; esac
üçlü

2
Kullanarak birden fazla ifadeyi önleyebilirsinizsed 's/^"\|"$//g'
tzrlk

287

Silmek için tr kullanın ":

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

Not : Bu, yalnızca öndeki ve sondaki tüm çift tırnak işaretlerini kaldırır.


16
OP'nin istediği bu değil, çünkü sadece önde gelen ve sondaki tüm tırnakları değil, tüm teklifleri de kaldırıyor.
Lenar Hoyt

19
OP'yi açıkça yanıtlamasa da, "/ yol / dosya adı" nın başında ve sonunda yalnızca çift tırnak bulunduğundan bu benim için çözülür. Gömülü çift tırnak yoktur. +1
WinEunuuchs2Unix

6
Bu çözüm birçok insanın istediği şey olacak. Birçok durumda, komut dosyası yazılabilir verileri kolayca tırnak işaretleri içine alınmış bir dizeye indirebilir.
Shadoninja

2
Zarif ve beni çok daha fazla deneme-hata-hata ayıklama zamanından kurtardı. Teşekkürler.
Scott Wade

İdeal olan budur ve bu yüzden kabul edilen cevaptan daha fazla oyu vardır.
apurvc

38

Bu, tüm çift tırnak işaretlerini kaldıracaktır.

echo "${opt//\"}"

1
Ancak, kaçan tırnak işaretleri ile kesilir, örn Don't remove this \" quote. :-(
gniourf_gniourf

Bu bir Bash uzantısıdır, bu nedenle genel olarak kabuk betiği için geçerli değildir. (Sorunun bunun önemli olup olmadığı konusunda belirsiz. Bunu Google'da bulan ziyaretçiler POSIX çözümü arıyor olabilir.)
üçlü

Mükemmellik! Tam olarak ihtiyacım olan şey. Sadece OP'nin istediği gibi değil, size çok sayıda cevap veren bu tür soruları seviyorum. Taşlar kabul edilmemiş cevaplarda!
dlite922

Korkarım OP sadece önde gelen / sondaki tırnakları kaldıran ve kaçanları tutan bir şey istiyor.
Fernando Paz

36

Xargs kullanmanın basit bir yolu vardır :

> echo '"quoted"' | xargs
quoted

xargs , komut yoksa, echo'yu varsayılan komut olarak kullanır ve girişten tırnak işaretleri çıkarır. Örneğin buraya bakınız .


echo '"quoted"' | xargs -> quoted
kyb

1
Bu çalışır, ancak yalnızca bir dizede çift sayıda tırnak için kullanılabilir. Tek bir sayı varsa, bir hata oluşturur.
James Shewey


19

En kısa yol - deneyin:

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

Aslında tüm "s (çift tırnak) 'dan kaldırır ( optgerçekten de başlangıç ​​ve bitiş dışında daha fazla çift tırnak olacak mı? Yani aslında aynı şey ve çok daha kısa ;-))


4
Tüm çift tırnak işaretlerini kaldırmak istiyorsanız, o zaman kullanmak daha da iyidir: "$ {opt // \" /} ". Pipo yok, subshell yok ... Ve eğer op içinde boşluk varsa, kaybedebilirsiniz her zaman gibi değişkenleri alıntı: echo "$ opt"
huelbois 16:12

Peki, değişken temelde httpd yapılandırma dosyasından DocumentRoot yolunu okur, bu yüzden burada bir teklif karakteri muhtemelen dizede olabilir durumda olabilir sanmıyorum. Ve bu sed çok daha temiz ve verimli .... Teşekkürler!
user1263746 16:12

16

Jq kullanıyorsanız ve tırnakları sonuçtan kaldırmaya çalışıyorsanız, diğer yanıtlar işe yarar, ancak daha iyi bir yol var. -rSeçeneği kullanarak, sonucu tırnak işaretleri olmadan çıkarabilirsiniz.

$ echo '{"foo": "bar"}' | jq '.foo'
"bar"

$ echo '{"foo": "bar"}' | jq -r '.foo'
bar

Ben kullanıyorum jqama jq da ASCII çıkışı -a(jq tarafında bir hata) ile çıktı eğer işe yaramazsa unutmayın
Can Poyrazoğlu

yqAyrıca -rseçeneği vardır:yq -r '.foo' file.yml
Hlib Babii

12

Güncelleme

Yalnızca bash / standart Linux komutlarını kullanarak bir dizede tek ve çift tırnakları soymanın basit ve zarif bir yanıtı :

BAR=$(eval echo $BAR)tırnak işaretleri şeritler BAR.

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

Hueybois'in cevabına dayanarak, çok fazla deneme yanılma sonrasında bu işlevi buldum:

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

Hiçbir şeyin yazdırılmasını istemiyorsanız, kanalları geliştirebilirsiniz /dev/null 2>&1.

Kullanımı:

$ BAR="FOO BAR"
$ echo BAR
"FOO BAR"
$ stripStartAndEndQuotes "BAR"
$ echo BAR
FOO BAR

1
Basit ve zarif olanı gerçekten sevmeme rağmen, eval'ün sadece çift tırnak kırpması yapmadığını, ancak aslında bir kod satırı olarak değerlendirdiğini fark etmeye değer olduğunu düşünüyorum. Bu nedenle, BAR kabuk tarafından değiştirilebilen başka diziler içerdiğinde bu teknik beklenmedik sonuçlar verebilir (örn. BAR = \ 'abc \' veya BAR = ab \ 'c veya BAR = a \ $ b veya BAR = a \ $ (ls *))
MaxP

11

Bash'teki en kolay çözüm:

$ s='"abc"'
$ echo $s
"abc"
$ echo "${s:1:-1}"
abc

Buna alt dize genişletme denir (bkz. Gnu Bash El Kitabı ve arama ${parameter:offset:length}). Bu örnekte alt dizeyi skonum 1'den başlayıp son ikinci konumda sona erdirir. Bunun nedeni, lengthnegatif bir değer olması durumunda , sonundan geriye doğru kayma olarak yorumlanmasıdır parameter.


vh.2


3

Bunu yapmanın başka bir yolu var. Sevmek:

echo ${opt:1:-1}

2

Benim versiyonum

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
}

İşlev, değişken ad (lar) ını kabul eder ve tırnak işaretleri yerinde tutar. Yalnızca eşleşen bir çift önde gelen ve sondaki tırnak işaretlerini çıkarır. Sondaki teklifin kaçıp kaçmadığını kontrol eder (öncesinde\ kaçan kendisi değil).

Deneyimlerime göre, bu gibi genel amaçlı dize yardımcı işlevleri (bunlardan bir kütüphane var), doğrudan dizeleri manipüle ederken, herhangi bir desen eşleşmesi kullanmadan ve özellikle herhangi bir alt kabuk oluşturmadan veya gibi harici araçları çağırırken en etkilidir sed, awkveya 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

Bunun çok eski bir soru olduğunu biliyorum, ama burada birisi için yararlı olabilecek başka bir sed varyasyonu var. Diğerlerinden farklı olarak, başlangıçta veya sonunda sadece çift tırnakların yerini alır ...

echo "$opt" | sed -r 's/^"|"$//g'
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.