मैं बैश कमांड स्ट्रिंग के वर्बेटिम वर्णों की जांच कैसे कर सकता हूं?


15

मेरा आज सुबह एक बाश टर्मिनल में यह अजीब व्यवहार था:

user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
bash: [: missing «]»
user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
true
  • पहली कमांड को गेडिट के साथ संपादित स्क्रिप्ट से चिपकाया गया था ।
  • दूसरे को सीधे टर्मिनल में टाइप किया गया था ।

कुछ खुदाई के बाद, मुझे पता चला है कि 30 वें चरित्र (क्लाइंट.कॉन्फ और "]" के बीच की जगह को हटा देना ) और इसे एक जगह के साथ बदलने से कमांड को फिर से काम करना पड़ा।

मेरी धारणा सही थी: एक अज्ञात खाली चरित्र कमांड में फिसल गया है , लेकिन सवाल यह है:

  1. मैं टर्मिनल में उन पात्रों को कैसे प्रकट कर सकता हूं ताकि मैं कमांड को डीबग कर सकूं? और अधिक महत्वपूर्ण:
  2. मैं इसे फिर से होने से कैसे रोक सकता हूं?

BTW, मैं Ubuntu 18.04 / फ्रेंच भाषा चला रहा हूं, जिस स्क्रिप्ट को मैं कमांड से चिपकाता हूं वह एक यूएसबी ड्राइव में है और हो सकता है कि इसे विंडोज पर भी संपादित किया गया हो।


आपके बहुत अच्छे उत्तरों के लिए धन्यवाद। खराब चरित्र c2 a0 गैर-ब्रेकिंग स्पेस UTF-8 वर्ण है। यह सवाल कि विशेष 'एम-बीएम-' चरित्र को कैसे हटाया जाए, इस चरित्र के बारे में दिलचस्प तथ्य है।

अजीब बात यह है कि स्क्रिप्ट इस चरित्र से मुक्त है। इसलिए मुझे नहीं पता कि यह कहां से आया है।


3
एक संपादक का उपयोग करें जो ऐसे पात्रों को उजागर करता है। सिंटेक्स हाइलाइटिंग बहुत मदद करता है, भी। वेब से टर्मिनल पर सीधे पेस्ट न करें, हमेशा उपरोक्त संपादक के माध्यम से जाएं।
चोराबा

2
यो अपनी इतिहास सूची में समस्या कमांड को ढूंढना चाहते हैं, फिर हेक्स डिस्प्ले प्रोग्राम के माध्यम से आउटपुट को पाइप कर सकते हैं। ताकि आपको लंबी सूची के माध्यम से वेड करने की आवश्यकता न हो, या तो इसे कमांड को इतिहास सूची के निचले भाग पर रखें और चलाएं history 2|xxd(क्योंकि historyकमांड स्वयं सूची में अंतिम है), या टाइप करें history|grep "CommandWithProblem"|xxd। आप इसके बजाय किसी भी अन्य हेक्स प्रदर्शन कार्यक्रम का उपयोग कर सकते हैं xxd, लेकिन यह मुझे पसंद है एक प्रारूप के लिए चूक है।
AFH

@ गैब्रिएल ग्लेन, टिक का उपयोग करके " स्वीकार किए गए " के रूप में सबसे अच्छा / सबसे उपयोगी / जो भी जवाब दें - कृपया जवाब देने में मदद करने के बजाय प्रत्येक पर टिप्पणी करें। जानकारी
Attie

1
@ एटीटीई, हां मैं करूंगा, मैं आमतौर पर सर्वोत्तम उत्तर स्वीकार करने से 24 घंटे पहले प्रतीक्षा करता हूं, जैसा कि इसमें सुझाया गया है: meta.stackexchange.com/questions/5234/…
गैब्रियल ग्लेन

1
व्यक्तिगत रूप से मैं उपयोग करेंगे set -x। यह आपको कमांड दिखाएगा और यह कैसे विभाजित है। यह जरूरी नहीं कि "बुरा चरित्र यहां" होगा, लेकिन यह आपको दिखाएगा कि बैश उस चरित्र पर विभाजित नहीं था।
पैट्रिक

जवाबों:


11

एक विकल्प उन पात्रों को देखना है जिन्हें आप हेक्स दर्शक या संपादक के साथ उपयोग करने का प्रयास कर रहे हैं। hexdumpएक अच्छा विकल्प है यदि आप टर्मिनल तक सीमित हैं।

$ hexdump -Cv <<"EOF"
> [ -f /etc/openvpn/client.conf ] && echo true
> EOF
00000000  5b 20 2d 66 20 2f 65 74  63 2f 6f 70 65 6e 76 70  |[ -f /etc/openvp|
00000010  6e 2f 63 6c 69 65 6e 74  2e 63 6f 6e 66 20 5d 20  |n/client.conf ] |
00000020  26 26 20 65 63 68 6f 20  74 72 75 65 0a           |&& echo true.|
0000002d

आप यहाँ देख सकते हैं कि space, close-square-brace, spaceसही कर रहे हैं - 0x20, 0x5D, 0x20

ये मान ASCII कोड हैं, जिन्हें हेक्साडेसिमल में प्रदर्शित किया गया है । सीमा के बाहर कोई भी मूल्य 0x20- 0x7Eएक " मुद्रण योग्य चरित्र " नहीं है , जहां तक ​​ASCII का संबंध है, और सबसे अधिक संभावना कमांड लाइन इंटरफेस के साथ अच्छी तरह से नहीं खेलेंगे।

नोट: मैंने ऊपर उदाहरण में उपयोग के लिए आपकी पहली " टूटी हुई " लाइन की प्रतिलिपि बनाई hexdumpहै, इसलिए कुछ ने आपके मूल स्रोत और आपके रेंडर किए गए प्रश्न के बीच ASCII स्थान के साथ नहीं-ए-एएससीआईआई-स्पेस को बदल दिया है ।


इसे दोहराने के लिए, निम्नलिखित कदम उठाएँ:

  1. टाइप करें hexdump -Cv <<"EOF"और दबाएँEnter
  2. उस पाठ को पेस्ट करें जिसका आप उपयोग करना चाहते हैं
  3. EOFअपनी खुद की एक पंक्ति पर टाइप करें , और दबाएंEnter

टर्मिनल और कमांड लाइन इंटरफेस विशेष पात्रों को अच्छी तरह से संभाल नहीं पाते हैं - जैसा कि आपने खोजा है। यदि आप दस्तावेज़ों को प्रारूपित करने में बहुत सावधानी नहीं रखते हैं, तो आपको " स्मार्ट कोट्स ", ई-डैश का उपयोग करके Microsoft Word (और अन्य) के साथ समस्याएँ भी होंगी , सूची जारी होती है ...

अंतर स्पॉट करें: (शीर्ष " स्मार्ट कोट्स " है, नीचे " स्ट्रेट कोट्स " है)

सीधे उद्धरण बनाम स्मार्ट उद्धरण का उदाहरण

$ hexdump -Cv <<"EOF"
> quoted string
> EOF
00000000  e2 80 9c 71 75 6f 74 65  64 20 73 74 72 69 6e 67  |...quoted string|
00000010  e2 80 9d 0a                                       |....|
00000014

यहाँ, खुला उद्धरण एक सरल ASCII उद्धरण (नहीं कर रहे हैं "), लेकिन एक यूनिकोड / हैं UTF-8 श्रृंखला - 0xE2, 0x80, 0x9C, या U+201C- जो के रूप में आप उम्मीद कर सकते टर्मिनल संभाल नहीं होंगे।

कीवी का सुझाव cat -Aभी काम करता है:

$ cat -A <<"EOF"
> quoted string
> EOF
M-bM-^@M-^\quoted stringM-bM-^@M-^]$

नोट: उपयोग करते समयecho "..." | hd, आप एक मौका खड़ा करते हैं जो बैश उस स्ट्रिंग के स्थानापन्न कर देगा जिसे आप निरीक्षण करने की कोशिश कर रहे हैं। यह विशेष रूप से एक स्क्रिप्ट के घटकों का निरीक्षण करने की कोशिश करते समय चिंता का विषय है।

उदाहरण के लिए प्रयास करें:

$ echo "${USER}"
attie

$ echo "`whoami`"
attie

$ echo "$(whoami)"
attie

$ cat <<EOF
> ${USER}
> EOF
attie

ये विधियां संबंधित पाठ के घटकों को प्रतिस्थापित कर रही हैं। इससे बचने के लिए, निम्नलिखित तरीकों में से एक का उपयोग करें। एकल उद्धरण ( '), और " उद्धृत हेरेडोक " ( "EOF") के उपयोग पर ध्यान दें ।

$ echo '${USER}'
${USER}

$ echo '`whoami`'
`whoami`

$ echo '$(whoami)'
$(whoami)

$ cat <<"EOF"
> ${USER}
> EOF
${USER}

यह समाधान काम करता है: echo "[ -f /etc/openvpn.ovpn ]" | hd रिटर्न [...] c2 a0 [...]। हम c2 a0 UT-8 वर्ण गैर-ब्रेकिंग स्पेस
गेब्रियल ग्लेन

18

आप विकल्प के catसाथ उपयोग कर सकते हैं -A: मैनुअल से:

   -A, --show-all
          equivalent to -vET
   -E, --show-ends
          display $ at end of each line
   -T, --show-tabs
          display TAB characters as ^I
   -v, --show-nonprinting
          use ^ and M- notation, except for LFD and TAB

तो cat -A yourscrip.shआपको अदृश्य और अजीब चरित्र दिखाएंगे।


7
यह समाधान काम करता है: echo "[ -f /etc/openvpn.ovpn ]" | cat -Aरिटर्न [ -f /etc/openvpn/client.ovpnM-BM- ]$। हम एम-बीएम- यूटी -8 चरित्र को गैर-ब्रेकिंग स्पेस
गेब्रियल ग्लेन

@ गैब्रिएलगेन को खुशी हुई कि इससे आपको मदद मिली।
कीवी

9

echo "<your command>" | hdकार्य करना चाहिए। कोड के साथ backspace (0x08) या वर्ण> = 80 देखें। echo "<your command>" | wc -bऔर जाँचना कि गिनती आपके द्वारा देखे जाने से मेल खाती है भी एक अच्छा विचार है।

अपने नाम में "कार्यालय" के साथ किसी भी चीज से उत्पन्न फ़ाइलों से सामान की नकल करना खतरनाक है, क्योंकि इस तरह के सॉफ़्टवेयर अक्सर पात्रों को बदलने के लिए स्वतंत्रता लेते हैं: फ्रेंच में, "गुइलेमेट्स" द्वारा प्रतिस्थापित दोहरे उद्धरणों के लिए देखें, अंग्रेजी में उनके द्वारा प्रतिस्थापित सादे उद्धरणों के लिए। खुले / करीब समकक्ष। मेरे द्वारा पाया गया सबसे कठिन एक फ़ाइल नाम (सर्वर डाउनटाइम के 3 दिन ...) के बीच में 0-चौड़ाई वाला गैर-ब्रेकिंग स्पेस था।


2
यह ध्यान देने योग्य hdहै, hexdumpजिसके लिए अटारी के उत्तर में भी उल्लेख किया गया है।
मिकेल Kjær

@ MikaelKjær - उबंटू पर, hdइसके बराबर है hexdump -C
AFH

1
@xenoid: मैंने कहा 'विंडोज पर एडिट किया हुआ है, ऑफिस राइटर के साथ एडिट नहीं किया गया है, हम पागल नहीं हैं;)। यदि इसे संपादित किया गया, तो यह नोटपैड ++ के साथ था।
गेब्रियल ग्लेन

1
यह समाधान काम करता है: echo "[ -f /etc/openvpn.ovpn ]" | hd रिटर्न [...] c2 a0 [...]। हम c2 a0 UT-8 वर्ण गैर-ब्रेकिंग स्पेस
गेब्रियल ग्लेन

2

बैश, और zsh जैसे अन्य गोले, एक संपादक में वर्तमान कमांड लाइन खोल सकते हैं। बश के लिए डिफ़ॉल्ट शॉर्टकट C-x C-e( CtrlX CtrlE) है, और यह पहले उपलब्ध में खुलता है $VISUAL, $EDITORऔर emacs। व्यवहार में यह डीबगिंग और जटिल कमांड को संशोधित करने के लिए अमूल्य है। इस पर निर्भर करता है कि आप इसे कैसे देखते हैं, यहाँ zash bash की तुलना में अधिक अनुकूल है: जब संपादक बाहर निकलता है, तो bash कमांड को तुरंत चलाता है, जबकि zsh आपको प्रेस करने के लिए इंतजार करता है Enter(आपको कमांड को संपादित करने के लिए अधिक मौके देता है)।

एक संपादक में कमांड खोलने के बाद, आप अपने संपादकों को गैर-एएससीआईआई पात्रों को अलग तरीके से दिखाने के लिए कॉन्फ़िगर कर सकते हैं।

उदाहरण के लिए, इन सेटिंग्स का उपयोग करके विम के साथ :

set encoding=latin1
set isprint=
set display+=uhex

यहाँ छवि विवरण दर्ज करें

या, अन्य उत्तरों के तरीकों को अपनाना:

bash-4.4$ f() { cat -A "$@"; false; }   # exit false to prevent bash from running the command
bash-4.4$ VISUAL=f
bash-4.4$ [ -f /etc/openvpn/client.conf ] && echo true  # C-x C-e here
[ -f /etc/openvpn/client.confM-BM- ] && echo true$
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.