शेल स्क्रिप्ट - एक चर से पहले और अंतिम उद्धरण (") को हटा दें


225

नीचे एक बड़ी स्क्रिप्ट से शेल स्क्रिप्ट का स्निपेट है। यह स्ट्रिंग से उन उद्धरणों को हटाता है जो एक चर द्वारा आयोजित किए जाते हैं। मैं इसे sed का उपयोग कर रहा हूं, लेकिन क्या यह कुशल है? यदि नहीं, तो कुशल तरीका क्या है?

#!/bin/sh

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

मैं उपयोग करने का सुझाव दूंगा sed "s/^\(\"\)\(.*\)\1\$/\2/g" <<<"$opt"। यह सिंटैक्स केवल qoutes को निकाल देगा जब एक मिलान जोड़ी होगी।
जॉन स्मिथ

@ जॉनसन मुझे एक शेल स्क्रिप्ट में उद्धरणों को स्वचालित रूप से बचना होगा, लेकिन मुझे ऐसा करने की आवश्यकता है कि क्या वे मेल खा रहे हैं या नहीं, इसलिए मैं शायद आपके द्वारा पोस्ट की गई उस अभिव्यक्ति का उपयोग नहीं करूंगा।
पिसिस

यदि आप इस प्रश्न को केवल सभी उद्धरणों को हटाना चाहते हैं, तो यह उत्तर देखें: askubuntu.com/a/979964/103498
गॉर्डन बीन

जवाबों:


268

देशी खोल उपसर्ग / प्रत्यय हटाने की सुविधा का उपयोग करते हुए एक सरल और अधिक कुशल तरीका है:

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

${opt%\"}प्रत्यय को हटा देगा "(शेल व्याख्या को रोकने के लिए बैकस्लैश के साथ भाग गया)।

${temp#\"}उपसर्ग को हटा देगा "(शेल व्याख्या को रोकने के लिए बैकस्लैश के साथ भाग गया)।

एक और लाभ यह है कि यह आसपास के उद्धरणों को तभी हटाएगा जब आसपास के उद्धरण हों।

BTW, आपका समाधान हमेशा पहले और अंतिम चरित्र को हटा देता है, जो कुछ भी वे हो सकते हैं (निश्चित रूप से, मुझे यकीन है कि आप अपने डेटा को जानते हैं, लेकिन यह हमेशा बेहतर है कि आप जो हटा रहे हैं वह सुनिश्चित हो)।

Sed का उपयोग करना:

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

(बेहतर संस्करण, जैसा कि jfgagne द्वारा इंगित किया गया है, प्रतिध्वनि से छुटकारा)

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

तो यह "कुछ भी नहीं के साथ एक प्रमुख की जगह , और "कुछ भी नहीं के साथ एक अनुगामी । एक ही आह्वान में (किसी अन्य पाइप को शुरू करने और उपयोग करने की कोई आवश्यकता नहीं है। -eआप कई पाठ प्रसंस्करण कर सकते हैं)।


14
आप सेड समाधान में पाइप से छुटकारा पा सकते हैं sed -e 's/^"//' -e 's/"$//' <<< $opt
jfg956

1
यह दुर्व्यवहार कर सकता है यह स्ट्रिंग में अग्रणी और अनुगामी दोनों बोली वर्ण नहीं है। उस इनायत को संभालने के लिए कोई सुझाव?
jsears

केवल मिलान किए गए बाहरी उद्धरणों को संभालने के लिए, @Joachim Pileborg द्वारा जवाब देखें
jsears

1
@ ज स हस? यह विशेष रूप से एक से शुरू होता है अगर एक है, और एक है तो अंत से एक है। यदि आप दोनों को उपस्थित होने तक हटाना नहीं चाहते हैं; हाँ, एक एकल sedरेगेक्स का उपयोग किया जा सकता है, या चर प्रतिस्थापन को किसी रेखा में लपेटा जा सकता हैcase $opt in '"'*'"') ... do it ... ;; esac
ट्रिपल

2
आप sed 's/^"\|"$//g'
tzrlk

287

हटाने के लिए tr का प्रयोग करें ":

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

नोट : यह सभी दोहरे उद्धरण हटाता है, न कि केवल प्रमुख और अनुगामी।


16
यह वह नहीं है जो ओपी ने पूछा है क्योंकि यह सभी उद्धरणों को हटाता है, न कि केवल प्रमुख और अनुगामी।
लेनार होयट

19
हालांकि ओपी का जवाब नहीं देना स्पष्ट रूप से यह मेरे लिए हल करता है क्योंकि "/ पथ / फ़ाइल-नाम" की शुरुआत और अंत में केवल दोहरे उद्धरण हैं। कोई एम्बेडेड दोहरे उद्धरण नहीं हैं। +1
विनयुनुच्स

6
यह समाधान वही होगा जो बहुत सारे लोग चाहते हैं। कई मामलों में, स्क्रिप्टिंग आसानी से उद्धरण से घिरे स्ट्रिंग के लिए व्यावहारिक डेटा को प्राप्त कर सकती है।
शादिनिजा

2
सुरुचिपूर्ण और मुझे बहुत अधिक परीक्षण-त्रुटि-डिबग समय से बचाया। धन्यवाद।
स्कॉट वेड

यह वही है जो आदर्श रूप से चाहता है और यही कारण है कि इसके पास स्वीकृत उत्तर की तुलना में अधिक वोट हैं।
अपूर्वी

38

यह सभी दोहरे उद्धरण चिह्नों को हटा देगा।

echo "${opt//\"}"

1
लेकिन बच गए उद्धरणों के साथ टूट जाएगा, जैसे Don't remove this \" quote,। :-(
gniourf_gniourf

यह एक बैश एक्सटेंशन है, इसलिए सामान्य रूप से शेल स्क्रिप्ट के लिए लागू नहीं है। (यह प्रश्न अस्पष्ट है कि क्या यह महत्वपूर्ण है या नहीं। Google में इसे खोजने वाले आगंतुक POSIX समाधान की तलाश में हो सकते हैं।)
tripleee

पूर्णता! बिल्कुल वही जो मुझे चाहिए था। मुझे इस तरह के सवाल बहुत पसंद हैं, जो आपको ओपी के अनुरोध का जवाब नहीं देते हैं। रत्नों को अस्वीकार्य उत्तर में हैं!
dlite922

मुझे डर है कि ओपी कुछ ऐसा चाहता है जो केवल प्रमुख / अनुगामी उद्धरणों को हटाता है और बच गए लोगों को रखता है।
फर्नांडो पाज़

36

Xargs का उपयोग करने का एक सीधा तरीका है :

> echo '"quoted"' | xargs
quoted

यदि कोई आदेश प्रदान नहीं किया गया है और इनपुट से स्ट्रिप्स उद्धरण, तो xargs डिफ़ॉल्ट कमांड के रूप में इको का उपयोग करता है। जैसे देखें यहाँ


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

1
यह काम करता है, लेकिन केवल एक स्ट्रिंग में उद्धरणों की संख्या के लिए। यदि कोई विषम संख्या है, तो यह एक त्रुटि उत्पन्न करता है।
जेम्स शेवी


19

सबसे छोटा तरीका - आज़माएँ:

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

यह वास्तव में सभी "एस (डबल कोट्स) को हटा देता है opt(क्या वास्तव में शुरुआत और अंत के अलावा कोई और डबल उद्धरण होने जा रहा है? तो यह वास्तव में एक ही बात है, और बहुत अधिक संक्षिप्त;;)


4
यदि आप सभी दोहरे उद्धरण चिह्नों को हटाना चाहते हैं, तो इसका उपयोग करना और भी बेहतर है: "$ {opt // \" /} "। कोई पाइप, कोई सबस्क्रिप्शन नहीं ... और सावधान रहें कि यदि आपके पास स्थान है, तो आप ढीले हो सकते हैं। उन्हें हमेशा। वैरिएबल जैसे: "$ ऑप्ट" प्रतिध्वनि करें
huelbois

खैर, वैरिएबल मूल रूप से httpd की कॉन्फिग फाइल से डॉक्यूमेंटरूट का रास्ता पढ़ता है, इसलिए मुझे नहीं लगता कि ऐसा कोई मामला हो सकता है जहां स्ट्रिंग में संभवतः एक कोट कैरेक्टर हो सकता है। और यह सेड बहुत ज्यादा नटखट और कुशल है .... धन्यवाद!
user1263746

16

यदि आप jq का उपयोग कर रहे हैं और परिणाम से उद्धरण निकालने की कोशिश कर रहे हैं, तो अन्य उत्तर काम करेंगे, लेकिन एक बेहतर तरीका है। -rविकल्प का उपयोग करके , आप कोई उद्धरण के साथ परिणाम का उत्पादन कर सकते हैं।

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

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

मैं उपयोग कर रहा हूं, jqलेकिन कृपया ध्यान दें कि यह काम नहीं करता है अगर jq ASCII आउटपुट के साथ भी आउटपुट कर रहा है -a(यह
jq

yqयह भी -rविकल्प है:yq -r '.foo' file.yml
हलीब बाबई

12

अपडेट करें

केवल बैश / मानक लिनक्स कमांड का उपयोग करके एक स्ट्रिंग में एकल और दोहरे उद्धरण स्ट्रिपिंग से एक सरल और सुरुचिपूर्ण उत्तर :

BAR=$(eval echo $BAR)स्ट्रिप्स से उद्धरण BAR

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

ह्यूयोबिस के उत्तर के आधार पर, मैं इस परीक्षण के बाद बहुत परीक्षण और त्रुटि के साथ आया:

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

यदि आप कुछ भी प्रिंट नहीं करना चाहते हैं, तो आप इसे प्राप्त कर सकते हैं /dev/null 2>&1

उपयोग:

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

1
हालांकि मुझे वास्तव में सरल और सुरुचिपूर्ण पसंद है, मुझे लगता है कि यह ध्यान देने योग्य है कि eval सिर्फ दोहरे उद्धरण ट्रिमिंग नहीं करता है, लेकिन वास्तव में कोड की एक पंक्ति के रूप में मूल्यांकन करता है। इसलिए यह तकनीक अप्रत्याशित परिणाम दे सकती है जब BAR में अन्य अनुक्रम होते हैं जो शेल द्वारा स्थानापन्न कर सकते हैं (उदाहरण के लिए BAR = \ 'abc \' या BAR = ab \ 'c या BAR = a $ b, या BAR = a $ $ (ls) *))
मैक्स

11

बैश में सबसे आसान उपाय:

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

इसे प्रतिस्थापन विस्तार कहा जाता है ( ग्नू बैश मैनुअल देखें और खोजें ${parameter:offset:length})। इस उदाहरण में यह प्रतिस्थापन की sस्थिति 1 से शुरू होकर दूसरे अंतिम स्थान पर समाप्त होता है। यह इस तथ्य के कारण है कि अगर lengthएक नकारात्मक मूल्य है, तो इसकी व्याख्या पीछे की तरफ से चलने वाले ऑफसेट के रूप में की जाती है parameter


नकारात्मक लंबाई bash v4.2 से समर्थित
mr.spuratic

8

यह सेड के उपयोग के बिना सबसे असतत तरीका है:

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

या

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

आउटपुट:

   quotes: "fish"
no quotes:  fish

मुझे यह एक स्रोत से मिला है ।


यह स्ट्रिंग के भीतर के साथ-साथ आसपास के लोगों के उद्धरणों को हटा देगा।
jsears

कमेंट्री के अलावा, यह 2012 से @ StevenPenny के जवाब के समान है ।
3

3

इसे करने का एक और तरीका है। पसंद:

echo ${opt:1:-1}

2

मेरा संस्करण

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
}

फ़ंक्शन जगह में चर नाम (ओं) और स्ट्रिप्स उद्धरण स्वीकार करता है। यह केवल अग्रणी और अनुगामी उद्धरणों की एक मिलान जोड़ी को स्ट्रिप्स करता है। यह जाँच नहीं करता है कि अनुगामी उद्धरण बच गया है (पहले से\ जिसके स्वयं भाग नहीं लिया गया है)।

मेरे अनुभव में, इस तरह के सामान्य प्रयोजन वाले स्ट्रिंग यूटिलिटी फ़ंक्शंस (मेरे पास उनकी एक लाइब्रेरी है) स्ट्रिंग्स में हेरफेर करते समय सबसे अधिक कुशल होते हैं, किसी भी पैटर्न से मेल खाते का उपयोग नहीं करते हैं और विशेष रूप से किसी भी उप-गोले का निर्माण नहीं करते हैं, या किसी भी बाहरी उपकरण जैसे sed, awkया 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

मुझे पता है कि यह एक बहुत पुराना सवाल है, लेकिन यहां एक और बदलाव है, जो किसी के लिए उपयोगी हो सकता है। दूसरों में से कुछ के विपरीत, यह केवल शुरुआत या अंत में दोहरे उद्धरणों की जगह लेता है ...

echo "$opt" | sed -r 's/^"|"$//g'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.