अप्रत्याशित टोकन के पास सिंटैक्स त्रुटि `फाई`


17

मैं जरूरी जवाब नहीं चाहता, लेकिन अगर कोई मुझे कुछ साहित्य या उदाहरणों की ओर इशारा कर सकता है। मैं इसका पता लगाना चाहूंगा।

जब मैं स्क्रिप्ट चलाता हूं तो मुझे एक त्रुटि मिलती है:

अनपेक्षित टोकन के पास सिंटैक्स त्रुटि fi

मैंने यह ifनिवेदन किया है कि मेरी समस्या मेरे ifबयानों को टिप्पणी करने और जोड़ने में है echo "$NAME"जो कि नामों को प्रदर्शित करता है /etc/

जब मैं परिवर्तन करते हैं, को दूर #से ifऔर fiऔर जोड़ने #के लिए wc -c "$NAME", मैं सिंटेक्स त्रुटि मैं उपरोक्त प्राप्त करते हैं। मैंने उसके ;बीच जोड़ा है ]। मैं भी thenबिना किसी संकल्प के अगली पंक्ति में चला गया हूं ।

#!/bin/bash
for NAME in /etc/*
do

     if [ -r "$NAME" -af "$NAME" ] then
          wc -c "$NAME"
     fi
done

9
जब भी आपके पास शेल सिंटैक्स त्रुटि होती है, तो एक अच्छा पहला कदम यह है कि अपने कोड को shellcheck.net में काटें और पेस्ट करें और उन त्रुटियों को ठीक करें जो इसे पहचानती हैं। अगर आपको इसके संदेशों को समझने में परेशानी है, तो यहां आकर पूछें।
जॉन 1024

2
क्या -afकरना चाहिए था?
लक्काचु

उस साइट के लिए धन्यवाद @ जॉन 1024 यह सबसे उपयोगी था, मैंने इसे भविष्य के संदर्भ के लिए बुकमार्क किया है।
क्रिस्टीना ए गुज़मैन

1
@ChristinaAGuzman ऐसे मामले -aमें बेमानी है क्योंकि हालत पहले से ही भीतर है -f। --- वैसे भी [ ](इस आदेश के रूप में भी उपलब्ध है test) के भीतर कई शर्तों -a(और) या -o(या) तार्किक ऑपरेटरों का उपयोग कर शामिल होना होगा, लेकिन जैसा कि नीचे दिए गए जवाब में यह सुझाव दिया गया था कि कई [ ]( test) आदेशों का उपयोग करना और शामिल होना बेहतर है उन्हें शेल ऑपरेटरों जैसे &&या का उपयोग करना ||
पाबौक

2
क्रिस्टीना, जैसा कि @ जॉन 1024 ने बताया, shellcheck.net बहुत स्पष्ट रूप से कुछ वाक्यविन्यास या यहां तक ​​कि गहरी गलतियों को दर्शाता है (जैसा कि सी कोड के लिए एक प्रकार का वृक्ष करता है)। मैं यह भी पढ़ने की सलाह देता हूं: mywiki.wooledge.org/BashPitashes (इसे कम से कम एक बार पढ़ें!) और mywiki.wooledge.org/BashFAQ और mywiki.wooledge.org/BashGitide साथ ही पढ़ना अच्छा है।
ओलिवियर दुलैक

जवाबों:


46

कीवर्ड की तरह if, then, else, fi, for, caseऔर इतने की जरूरत पर एक जगह है जहाँ खोल एक कमांड नाम की उम्मीद में किया जाना है। अन्यथा उन्हें साधारण शब्दों के रूप में माना जाता है। उदाहरण के लिए,

echo if

बस प्रिंट ifकरता है, यह एक सशर्त अनुदेश शुरू नहीं करता है।

इस प्रकार, लाइन में

if [ -r "$NAME" -af "$NAME" ] then

शब्द thenकमांड का एक तर्क है [(जिसके बारे में यह शिकायत होगी कि क्या यह कभी चलाने के लिए मिला है)। शेल के लिए खोज जारी है then, और fiकमांड स्थिति में एक पाता है । चूँकि वहाँ ifअभी भी इसकी तलाश है then, fiअप्रत्याशित है, इसमें एक वाक्यविन्यास त्रुटि है।

आपको कमांड टर्मिनेटर डालने की आवश्यकता है thenताकि यह एक कीवर्ड के रूप में पहचाना जाए। सबसे आम कमांड टर्मिनेटर एक लाइन ब्रेक है, लेकिन इससे पहले then, अर्धविराम (जो कि लाइन ब्रेक के बिल्कुल समान अर्थ है) का उपयोग करना आम है।

if [ -r "$NAME" -af "$NAME" ]; then

या

if [ -r "$NAME" -af "$NAME" ]
then

एक बार जब आप तय कर लेते हैं कि आपको कमांड से एक और त्रुटि मिलेगी [क्योंकि यह समझ में नहीं आता है -af। आप निश्चित रूप से मतलब है

if [ -r "$NAME" -a -f "$NAME" ]; then

यद्यपि परीक्षण कमांड विकल्प की तरह दिखते हैं, आप उन्हें इस तरह से बंडल नहीं कर सकते। वे [कमांड के ऑपरेटर हैं और उन्हें प्रत्येक को एक अलग शब्द (जैसे [और ]) होना चाहिए।

वैसे, हालांकि [ -r "$NAME" -a -f "$NAME" ]काम करता है, मैं या तो लिखने की सलाह देता हूं

[ -r "$NAME" ] && [ -f "$NAME" ]

या

[[ -r $NAME && -f $NAME ]]

यह [ … ]सशर्त सरल रखने के लिए सबसे अच्छा है क्योंकि [कमांड ऑपरेटरों को ऑपरेंड से आसानी से अलग नहीं कर सकता है। यदि $NAMEएक ऑपरेटर की तरह दिखता है और उस स्थिति में दिखाई देता है जहां ऑपरेटर मान्य है, तो इसे ऑपरेटर के रूप में पार्स किया जा सकता है। इस उत्तर में देखे गए साधारण मामलों में ऐसा नहीं होगा, लेकिन अधिक जटिल मामले जोखिम भरे हो सकते हैं। [शेल के लॉजिकल ऑपरेटर्स को अलग-अलग कॉल के साथ यह लिखना इस समस्या से बचा जाता है।

दूसरा सिंटैक्स [[ … ]]सशर्त निर्माण का उपयोग करता है जो बैश में मौजूद है (और ksh और zsh, लेकिन सादे श नहीं)। यह निर्माण विशेष सिंटेक्स, जबकि है [इस प्रकार आप जैसी चीजों का उपयोग कर सकते किसी अन्य आदेश की तरह पार्स किया गया है, &&अंदर और आप कुछ स्ट्रिंग ऑपरेटरों के लिए तर्क को छोड़कर बोली चर की जरूरत नहीं है ( =, ==, !=, =~) (देखें जब आवश्यक डबल के हवाले से है ? जानकारी के लिए)।


ध्यान दें कि if [[ 1 ]] then [[ 2 ]] fiksh, pdksh और zsh में काम करता है। if(:)then(:)fiसभी गोले में काम करता है।
स्टीफन चेज़लस

12

निम्नानुसार देखें कि क्या बदला है

अगर [-r "$ NAME" -a -f "$ NAME"] ; फिर
# ^ ^ ^ ^ ^ ^ ^
     wc -c "$ NAME"
फाई

यदि आप यदि ब्लॉक में सभी कमांड को हटाना चाहते हैं, तो आपको कम से कम इसमें एक कोलोन जोड़ने की आवश्यकता है, जैसे

if [ -r "$NAME" -a -f "$NAME" ]; then
    :
fi

या एक पंक्ति संस्करण

if [ -r "$NAME" -a -f "$NAME" ]; then :; fi


2

दूसरों ने पहले ही बताया, लेकिन यदि आप आधिकारिक संदर्भ की तलाश कर रहे हैं तो आरटीएम

यदि सूची; फिर सूची; [एलिफ सूची; फिर सूची; ] ... [अन्य सूची;] फाई

यदि सूची निष्पादित की गई है। यदि इसकी निकास स्थिति शून्य है, तो सूची को निष्पादित किया जाता है। अन्यथा, प्रत्येक एलीफ सूची को बदले में निष्पादित किया जाता है, और यदि इसकी निकास स्थिति शून्य है, तो तत्कालीन सूची को निष्पादित किया जाता है और कमांड पूरा होता है। अन्यथा, यदि मौजूद है, तो दूसरी सूची निष्पादित की जाती है। एग्जिट स्टेटस अंतिम कमांड की एक्जिट स्थिति है, या शून्य, यदि कोई शर्त सही नहीं है।

आपकी याद आ रही है ;

और के लिए वाक्यविन्यास listमें वर्णित हैman test

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.